diff -u --recursive --new-file v2.2.6/linux/CREDITS linux/CREDITS --- v2.2.6/linux/CREDITS Tue Mar 23 14:35:46 1999 +++ linux/CREDITS Fri Apr 23 08:42:03 1999 @@ -810,12 +810,13 @@ D: Transmeta BOFH in my copius free time N: Dirk Hohndel -E: hohndel@aib.com +E: hohndel@suse.de D: The XFree86[tm] Project -S: AIB Software Corporation -S: 46030 Manekin Plaza, Suite 160 -S: Dulles, Virginia 20166 -S: USA +D: USB mouse maintainer +S: SuSE Rhein/Main AG +S: Mergenthalerallee 45-47 +S: 65760 Eschborn +S: Germany N: Kenji Tsutomu Hollis E: khollis@bitgate.com @@ -1874,7 +1875,7 @@ N: Linus Torvalds E: torvalds@transmeta.com -W: http://www.cs.helsinki.fi/~torvalds/ +W: http://www.cs.helsinki.fi/Linus.Torvalds P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A BE 67 3C 24 03 13 62 C8 D: Original kernel hacker S: 1050 Woodduck Avenue diff -u --recursive --new-file v2.2.6/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.2.6/linux/Documentation/Configure.help Fri Apr 16 14:47:30 1999 +++ linux/Documentation/Configure.help Tue Apr 20 15:17:20 1999 @@ -7443,6 +7443,26 @@ case insensitive, and case in names is preserved. Say Y. You can disable it at mount time with the -N os2 parameter of ncpmount. +Lowercase DOS filenames on LONG namespace volume +CONFIG_NCPFS_SMALLDOS + Saying Y here will convert every filename with creator/owner DOS + namespace on NetWare servers to lowercase characters as silently + kernel does when you mount NetWare file server volumes with DOS + namespace without OS2/LONG namespace support. Saying N here will + give you these filenames with uppercase characters. + + This is only cosmetic option because of OS2/LONG namespace is + case insensitive. The only major reason for this option is + backward compatibility when you want to do step from DOS to + OS2/LONG namespace support. Long filenames (created by Win95) + will not be affected. + + This option does not solve a problem that filenames appear + differently in Linux box and in MS environment because of MS + does an additional conversions on client side. You can achieve + simillar effects enabling ncpfs option "Allow using of Native + Language Support" below. + Allow mounting of volume subdirectories CONFIG_NCPFS_MOUNT_SUBDIR Allows you to mount not only whole servers or whole volumes, but @@ -7461,6 +7481,25 @@ servers. Do not say Y if security is primary for you because root can read your session key (from /proc/kcore). +Allow using of Native Language Support +CONFIG_NCPFS_NLS + Allows you to use codepages and I/O charsets for file name translation + between file system on server and input/output. This may be useful, + if you want to access to the server with other operating systems, + e.g. Windows 95. See also NLS for more Information. + + To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer. + +Symbolic links and mode permission bits +CONFIG_NCPFS_EXTRAS + This enables the use of symbolic links and an execute permission + bit on NCPFS. The file server need not have long name space or NFS + name space loaded for these to work, they are stored using rarely + found combinations of Hidden, System and Shared flags. + + To use the new attributes, you are recommended to use the flags + '-f 600 -d 755' on the ncpmount commandline. + nls codepage 437 CONFIG_NLS_CODEPAGE_437 The Microsoft fat filesystem family can deal with filenames in diff -u --recursive --new-file v2.2.6/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt --- v2.2.6/linux/Documentation/fb/matroxfb.txt Tue Jan 19 11:32:50 1999 +++ linux/Documentation/fb/matroxfb.txt Tue Apr 20 15:13:00 1999 @@ -1,6 +1,6 @@ [This file is cloned from VesaFB. Thanks go to Gerd Knorr] -what is matroxfb? +What is matroxfb? ================= This is a driver for a graphic framebuffer for Matrox devices on @@ -221,6 +221,8 @@ sync:X - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity. If bit 3 (value 0x08) is set, composite sync instead of HSYNC is generated. If bit 5 (value 0x20) is set, sync on green is turned on. + Do not forget that if you want sync on green, you also probably + want composite sync. Default depends on `vesa'. depth:X - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on `vesa'. @@ -284,8 +286,6 @@ + current fbset is not able to set 15bpp videomode: you must specify depth==16 and green.length==5. fbset does not allow you to set green.length. - + hardware cursor is available only in accelerated videomodes. Maybe that - this is misfeature and not feature. + text mode uses 6 bit VGA palette instead of 8 bit (one of 262144 colors instead of one of 16M colors). It is due to hardware limitation of MilleniumI/II and SVGALib compatibility. diff -u --recursive --new-file v2.2.6/linux/Documentation/filesystems/vfs.txt linux/Documentation/filesystems/vfs.txt --- v2.2.6/linux/Documentation/filesystems/vfs.txt Wed Jul 1 19:38:51 1998 +++ linux/Documentation/filesystems/vfs.txt Tue Apr 27 09:24:34 1999 @@ -4,7 +4,7 @@ Richard Gooch - 27-JUN-1998 + 23-APR-1999 Conventions used in this document
@@ -129,7 +129,7 @@ name: the name of the filesystem type, such as "ext2", "iso9660", "msdos" and so on - fs_flags: various flags (i.e. if it is a read-only FS) + fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) read_super: the method to call when a new instance of this filesystem should be mounted diff -u --recursive --new-file v2.2.6/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt --- v2.2.6/linux/Documentation/scsi-generic.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/scsi-generic.txt Sat Apr 24 17:49:37 1999 @@ -0,0 +1,636 @@ + Notes on Linux's SG driver version 2.1.30 + ----------------------------------------- + 990328 + +Introduction +============ +These are notes on the Linux SCSI generic packet device driver (sg) +describing version 2.1.30 . The original driver was written by Lawrence +Foard and has remained in place with minimal changes since circa 1992. +Version 2 of this driver remains backward compatible (binary and +source **) with the original. It adds scatter gather, command queuing, +per file descriptor sequencing, asynchronous notification and better +error reporting. + +Sg is one of the four "high level" SCSI device drivers along with +sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized +(but lower level) than its sibling and tends to be used on SCSI devices +that don't fit into the already serviced categories. Thus sg is used for +scanners, cd writers and reading audio cds amongst other things. + +The interface and usage of the original sg driver has been documented +by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy +of the document is version 1.5 dated 7th May 1996. It can found at +ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/SCSI-Programming-HOWTO . +Amongst other things it has a lot of tables from the SCSI-2 standard +that are very useful for programming this interface. + +** It is possible to write applications that perform differently +depending on whether they are using the original or this version of +the sg device driver. The author is not aware of any useful applications +that have problems with version 2 (yet). + + +Architecture +============ +The SCSI generic packet device driver (sg) is a character based device. +It is one of the four high level device driver in the SCSI sub-system; +the others are sd (for direct-access devices - disks), st (for tapes) +and sr (for data cdroms). The other three devices are block devices. + +The unifying layer of the SCSI sub-system in the so-called mid-level. +Below that are all the drivers for the various adapters supported by +Linux. + +Since sg is a character device it supports the traditional Unix +system calls of open(), close(), read(), write() and ioctl(). Two other +related system calls: poll() and fcntl() are added to this list and +how they interact with the sg device driver is documented later. + +An SG device is accessed by write()ing SCSI commands plus any associated +outgoing data to it; the resulting status codes and any incoming data are +then obtained by a read() call. The device can be opened O_NONBLOCK +(non-blocking) and poll() used to monitor its progress. The device may be +opened O_EXCL which excludes other "sg" users from this device (but not +"sd", "st" or "sr" users). The buffer given to the write() call is made +up as follows: + - struct sg_header image (see below) + - scsi command (6, 10 or 12 bytes long) + - data to be written to the device (if any) + +The buffer received from the corresponding read() call contains: + - struct sg_header image (check status/errors + sense_buffer) + - data read back from device (if any) + +The given SCSI command has its LUN field overwritten by the LUN value of +the associated sg device that has been open()ed. + + +sg_header +========= +This is the name of the control structure that conveys information +about the length of data to be read/written by the associated SCSI +command. It also conveys error and status information from the +read() call. An instance of this structure is the first thing that +is placed in the data buffers of both write() and read(). + +In its original form it looked like this: +struct sg_header { + int pack_len; + int reply_len; + int pack_id; + int result; + unsigned int twelve_byte:1; + unsigned int other_flags:31; + unsigned char sense_buffer[16]; +}; /* this structure is 36 bytes long */ + +The 'pack_len' is bizzare and ends up having the 'reply_len' put in it +(perhaps it had a use at some stage). + +The 'reply_len' is the length of the data the corresponding read() +will/should request (including the sg_header). + +The 'pack_id' is not acted upon by the sg device driver but is conveyed +back to the corresponding read() so it can be used for sequencing by an +application. + +The 'result' is also bizzare, turning certain types of host codes it 0 (no +error), EBUSY or EIO. With better error reporting now available, the +'result' is best ignored. + +The 'twelve_byte' field overrides the internal SCSI command length "guessing" +algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces +a command lenth of 12 bytes. +The command length "guessing" algorithm is as follows: +Group: 0 1 2 3 4 5 6 7 +Length: 6 10 10 12 12 12 10 10 + +'other_flags' was originally documented as "not used" but some current +applications assume it has 0 placed in it. + +The 'sense_buffer' is the first 16 bytes of SCSI sense buffer that is +returned when the target returns a SCSI status code of CHECK_CONDITION +or COMMAND_TERMINATED [or (driver_status & DRIVER_SENSE) is true]. This +buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately +this is unlikely to happen in the 2.2.x series of kernels. + +The new sg_header offered in this driver is: +#define SG_MAX_SENSE 16 +struct sg_header +{ + int pack_len; /* [o] reply_len (ie useless) ignored as input */ + int reply_len; /* [i] max length of expected reply (inc. sg_header) */ + int pack_id; /* [io] id number of packet (use ints >= 0) */ + int result; /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */ + unsigned int twelve_byte:1; + /* [i] Force 12 byte command length for group 6 & 7 commands */ + unsigned int target_status:5; /* [o] scsi status from target */ + unsigned int host_status:8; /* [o] host status (see "DID" codes) */ + unsigned int driver_status:8; /* [o] driver status+suggestion */ + unsigned int other_flags:10; /* unused */ + unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] when target_status is + CHECK_CONDITION or COMMAND_TERMINATED this is output. */ +}; /* This structure is 36 bytes long on i386 */ + +Firstly the new header is binary compatible with the original. This is +important for keeping existing apps working without recompilation. + +Only those elements (or fields) that are new or in some way different +from the original are documented below. + +'pack_id' becomes input to a read() when ioctl(sg_fd, SG_SET_FORCE_PACK_ID, +&one) is active. A 'pack_id' of -1 is interpreted as fetch the oldest +waiting packet; any other value will cause the read() to wait (or yield +EAGAIN) until a packet with that 'pack_id' becomes available. In all cases +the value of 'pack_id' available after a read() is the value given to that +variable in the prior, corresponding write(). + +The 'target_status' field is always output and is the (masked and shifted +1 bit right) SCSI status code from the target device. The allowable +values are (found in ): +/* N.B. 1 bit offset from usual SCSI status values */ +#define GOOD 0x00 +#define CHECK_CONDITION 0x01 +#define CONDITION_GOOD 0x02 +#define BUSY 0x04 +#define INTERMEDIATE_GOOD 0x08 +#define INTERMEDIATE_C_GOOD 0x0a +#define RESERVATION_CONFLICT 0x0c +#define COMMAND_TERMINATED 0x11 +#define QUEUE_FULL 0x14 +When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the +'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE) +is true then the 'sense_buffer' is also output (this seems to occur when +the scsi ide emulation is used). When the 'sense_buffer' is output the +SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) . + +The 'host_status' field is always output and has the following values +whose "defines" are not visible outside the kernel (unfortunately): +#define DID_OK 0x00 /* NO error */ +#define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ +#define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ +#define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */ +#define DID_BAD_TARGET 0x04 /* BAD target. */ +#define DID_ABORT 0x05 /* Told to abort for some other reason */ +#define DID_PARITY 0x06 /* Parity error */ +#define DID_ERROR 0x07 /* Internal error */ +#define DID_RESET 0x08 /* Reset by somebody. */ +#define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ +#define DID_PASSTHROUGH 0x0a /* Force command past mid-layer */ +#define DID_SOFT_ERROR 0x0b /* The low level driver just wish a retry */ + +The 'driver_status' field is always output. When ('driver_status' & +DRIVER_SENSE) is true the 'sense_buffer' is also output. The following +values whose "defines" are not visible outside the kernel (unfortunately) +can occur: +#define DRIVER_OK 0x00 /* Typically no suggestion */ +#define DRIVER_BUSY 0x01 +#define DRIVER_SOFT 0x02 +#define DRIVER_MEDIA 0x03 +#define DRIVER_ERROR 0x04 +#define DRIVER_INVALID 0x05 +#define DRIVER_TIMEOUT 0x06 +#define DRIVER_HARD 0x07 +#define DRIVER_SENSE 0x08 +/* above status 'or'ed with one of the following suggestions */ +#define SUGGEST_RETRY 0x10 +#define SUGGEST_ABORT 0x20 +#define SUGGEST_REMAP 0x30 +#define SUGGEST_DIE 0x40 +#define SUGGEST_SENSE 0x80 + +'other_flags' still remains as a 10 bit field, so code that places 0 in it +will still be happy. It is not used. + + +memory +====== +Memory is a scarce resource in any computer. Sg needs to reserve memory +suitable for DMA roughly equal in size to the maximum of the write and +read data buffers for each packet. This DMA memory is obtained at the time +of a write() and released when the corresponding read() is called (although +if memory is tight it may be using the buffer reserved by the open() ). + +Linux obtaining memory a challenge for several reasons. The memory pool +that sg uses is in common with all other device drivers and all user +processes. In this environment the only way to 99.9% guarantee a driver +will have memory in Linux is to build it into the kernel (ie not as a +module) and then reserve it on initialization before user processes get +a chance. [Of course, another driver initialized before sg could take +all available memory ...] Another problem is the biggest contiguous +chunk of memory that can be obtained from the kernel is 32 * PAGE_SIZE +(which is 128KBytes on i386). As memory gets "splintered" there is a good +chance that buffers won't be available (my machine has 64 MBytes of RAM +and has 3 available at the moment). + +The original sg driver used the following technique: grab a SG_BIG_BUFF +sized buffer at driver initialization and use it for all requests greater +than PAGE_SIZE (4096 bytes on i386). By default SG_BIG_BUFF is set to +32 KBytes in the origianl driver but many applications suggest that the +user increases this number. Linux limits the biggest single buffer of +this type to 32 * PAGE_SIZE (128KBytes on i386). Unfortunately if the +sg driver is a module then there is a high chance a contiguous block of +that large size will not be available at module initialization. + +The author has found no "silver bullet" solution but uses multiple +techniques hoping that at least one is able provide memory at the critical +time. Listed below are some of these techniques: + - use scatter gather: then instead of one large buffer needing to + be found, multiple smaller buffer can be used + - use memory above the 16MByte level: the original driver limited + itself to obtaining memory below the 16MByte level (on the i386) + due to the shortcomings of DMA on ISA adapters. Yet more and more + people use PCI adapters that don't have this problem. So make + the decision based on the capabilities of the host adpater + associated with the current SCSI device + - reserve some memory at open() for emergencies but otherwise + fetch and release it on a per packet basis + - if the kernel is short of memory then dip into the SCSI DMA + pool (maintained by the mid-level driver) to a limited amount + + + +System Calls +============ +What follows are descriptions of the characteristics of the standard +Unix operating system calls when applied to a SCSI generic device +using this version of the device driver. + +open +---- +The filename should be an 'sg' device such as +/dev/sg[a-z] +/dev/sg[0,1,2,...] +or a symbolic link to one of these. [Devfs has its own sub-directory for +sg devices.] It seems as though SCSI devices are allocated to sg minor +numbers in the same order as they appear in 'cat /proc/scsi/scsi'. +Sg is a "character" based Linux device driver. This means it has an +open/close/read/write/ioctl type interface. + +Flags can be either O_RDONLY or O_RDWR or-ed with either +O_EXCL waits for other opens on sg device to be closed before + proceeding. If O_NONBLOCK is set then yields EBUSY when + someone else has the sg device open. The combination of + O_RDONLY and O_EXCL is disallowed. +O_NONBLOCK Sets non-blocking mode. Calls that would otherwise block + yield EAGAIN (eg read() ) or EBUSY (eg open() ). + +The original version of sg did not allow the O_RDONLY (yielding a EACCES +error). This version allows it for accessing ioctls (e.g. doing an sg +device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be +allowed. + +By default, sequencing is per file descriptor in this version of sg. This +means, for example that 2 processes can independently manipulate the same +sg device at the same time. This may or may not make sense depending on +the application: 2 processes (logically) reading from the same direct access +device (ie a disk) is ok while running 2 instances of cd writing software +on the same device at the same time probably wouldn't be a good idea. The +previous version of sg supported only per device sequencing and this can +still be selected with the SG_SET_MERGE_FD,1 ioctl(). + +The driver will attempt to reserve SG_SCATTER_SZ bytes (32KBytes in the +current sg.h) on open() for "emergency" situations. If this is unavailable +it will halve its request and try again. It gives up if PAGE_SIZE bytes +(4096 bytes on i386) cannot be obtained so no memory is reserved. In this +case open() will still return successfully. The actual amount of memory +reserved can be found with the SG_GET_RESERVED_SIZE ioctl(). + +Returns a file descriptor if >= 0 , otherwise -1 implies an error. + +Error codes (value in 'errno' after -1 returned): +ENODEV sg not compiled into kernel or the kernel cannot find the + sg module (or it can't initialize itself (low memory??)) +ENXIO either scsi sub-system is currently processing some error + (eg doing a device reset) or the sg driver/module removed + or corrupted +EBUSY O_NONBLOCK set and some user of this sg device has O_EXCL + set while someone is already using this device +EINTR while waiting for an "exclusive" lock to clear, a signal + is received, just try again ... +ENOMEM An attempt to get memory to store this open's context + failed (this was _not_ a request to reserve DMA memory) +EACCES An attempt to use both O_RDONLY and O_EXCL + + +write +----- +Even though sg is a character-based device driver it sends and receives +packets to/from the associated scsi device. Write() is used to send a +packet containing 2 mandatory parts and 1 optional part. The mandatory +parts are: + - a control block (an instance of struct sg_header) + - a SCSI command (6, 10 or 12 bytes long) +The optional part is: + - outgoing data (eg if a SCSI write command is being sent) +These should appear as one contiguous string in the buffer given to +write() in the above order with no pad characters. + +If a write() accepts this packet then at some later time the user should +call a read() to get the result of the SCSI command. The previous sg +driver enforced a strict write()/read()/write()/read() regime so that a +second write() would block until first read() was finished. This sg +driver relaxes that condition and thereby allows command queuing +(limit is SG_MAX_QUEUE (16) outstanding packets per file descriptor). +However, for backward compatibility, command queuing is turned off +by default (#define SG_DEF_COMMAND_Q 0 in sg.h). This can be changed +via the the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing +the above define to 1]. + +In this sg driver a write() should return more or less immediately. + +Returns number of bytes written if > 0 , otherwise -1 implies an error. + +Error codes (value in 'errno' after -1 returned): +ENXIO either scsi sub-system is currently processing some error + (eg doing a device reset) or the sg driver/module removed + or corrupted +EACCES opened with RD_ONLY flag +EIO incoming buffer too short. It should be at least (6 + + sizeof(struct sg_header))==42 bytes long +EDOM a) command queuing off: a packet is already queued + b) command queuing on: too many packets queued + (SG_MAX_QUEUE exceeded) +EAGAIN SCSI mid-level out of command blocks (rare), try again. + This is more likely to happen when queuing commands, + so wait a bit (eg usleep(10000) ) before trying again +ENOMEM can't get memory for DMA. Take evasive action ... + (see section on memory) + + +read +---- +Read() is used to receive a packet containing 1 mandatory part and 1 +optional part. The mandatory part is: + - a control block (an instance of struct sg_header) +The optional part is: + - incoming data (eg if a SCSI read command was sent by earlier write() ) +The buffer given to a read() and its corresponding count should be +sufficient to accommodate this packet to avoid truncation. Truncation has +occurred if count < sg_header::replylen . + +By default, read() will return the oldest packet queued up. If the +SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to +fetch the packet whose pack_id (given earlier to write()) matches the +sg_header::pack_id given to this read(). If not available it will either +wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given +to read() will match the oldest packet. + + +Returns number of bytes read if > 0 , otherwise -1 implies an error. +Unfortunately the return value in the non-error case is simply the +same as the count argument. It is not the actual number of bytes +DMA-ed by the SCSI device. This driver is currently unable to provide +such an underrun indication. + +Error codes (value in 'errno' after -1 returned): +ENXIO either scsi sub-system is currently processing some error + (eg doing a device reset) or the sg driver/module removed + or corrupted +EAGAIN either no waiting packet or requested packet is not + available while O_NONBLOCK flag was set +EINTR while waiting for a packet, a signal is received, just + try again ... +EIO if the 'count' given to read() is < sizeof(struct sg_header) + and the 'result' element in sg_header is non-zero. Not a + recommended error reporting technique + + +close +----- +Preferably a close() should be done after all issued write()s have had +their corresponding read() calls completed. Unfortunately this is not +always possible. The semantics of close() in Unix are to return more +or less immediately (ie not wait on any event) so the driver needs to +arrange to an orderly cleanup of those packets that are still "in +flight". + +A process that has an open file descriptor to an sg device may be aborted +(eg by a kill signal). In this case, the kernel automatically calls close +(which is called 'sg_release()' in the version 2 driver) to facilitate +the cleanup mentioned above. + +A problem persists in version 2.1.8 if the sg driver is a module and is +removed while packets are still "in flight". Hopefully this will be soon +fixed. + +Returns 0 if successful, otherwise -1 implies an error. + +Error codes (value in 'errno' after -1 returned): +ENXIO sg driver/module removed or corrupted + +ioctl (sg specific) +------------------- +Ken Thompson (or perhaps some other Unix luminary) described ioctl() as +the "garbage bin of Unix". This driver compounds the situation by adding +around 18 more commands. These commands either yield state information (10 +of them), change the driver's characteristics (8 of them) or allow direct +communication with the common SCSI mid-level driver. + +Those commands with an appended "+" are new in version 2. + +Those commands with an appended "W" are only accessible from file +descriptors opened with O_RDWR. They will yield EACCES otherwise. + +SG_GET_TIMEOUT: +Ignores its 3rd argument and _returns_ the timeout value (which will be +>= 0 ). The unit of this timeout is "jiffies" which are currently 10 +millisecond intervals on i386 (less on an alpha). Linux supplies +a manifest constant HZ which is the number of "jiffies" in 1 second. + +SG_SET_TIMEOUT: +Assumes 3rd argument points to an int containing the new timeout value +for this file descriptor. The unit is a "jiffy". Packets that are +already "in flight" will not be effected. The default value is set +on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). + +SG_EMULATED_HOST: +Assumes 3rd argument points to an int and outputs a flag indicating +whether the host (adapter) is connected to a real SCSI bus or is +emulated one (eg ide-scsi device driver). A value of 1 means emulated +while 0 is not. + +SG_SET_FORCE_LOW_DMA +: +Assumes 3rd argument points to an int containing 0 or 1. 0 (default) +means sg decides whether to use memory above 16 Mbyte level (on i386) +based on the host adapter being used by this SCSI device. Typically +PCI SCSI adapters will indicate they can DMA to the whole 32 bit address +space. +If 1 is given then the host adapter is overridden and only memory below +the 16MB level is used for DMA. A requirement for this should be +extremely rare. If the "reserve" buffer allocated on open() is not in +use then it will be de-allocated and re-allocated under the 16MB level +(and the latter operation could fail yielding ENOMEM). +Only the current file descriptor is effected. + +SG_GET_LOW_DMA +: +Assumes 3rd argument points to an int and places 0 or 1 in it. 0 +indicates the whole 32 bit address space is being used for DMA transfers +on this file descriptor. 1 indicates the memory below the 16MB level +(on i386) is being used (and this may be the case because the host +adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 . + +SG_GET_SCSI_ID +: +Assumes 3rd argument is pointing to an object of type Sg_scsi_id and +populates it. That structure contains ints for host_no, channel, +scsi_id, lun and scsi_type. Most of this information is available from +other sources (eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) +but tends to be awkward to collect. + +SG_SET_FORCE_PACK_ID +: +Assumes 3rd argument is pointing to an int. 0 (default) instructs read() +to return the oldest (written) packet if multiple packets are +waiting to be read (when command queuing is being used). +1 instructs read() to view the sg_header::pack_id as input and return the +oldest packet matching that pack_id or wait until it arrives (or yield +EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1 +given to read() in the mode will match the oldest packet. +Only the current file descriptor is effected by this command. + +SG_GET_LOW_DMA +: +Assumes 3rd argument points to an int and places the pack_id of the +oldest (written) packet in it. If no packet is waiting to be read then +yields -1. + +SG_GET_NUM_WAITING +: +Assumes 3rd argument points to an int and places the number of packets +waiting to be read in it. + +SG_GET_SG_TABLESIZE +: +Assumes 3rd argument points to an int and places the maximum number of +scatter gather elements supported by the host adapter. 0 indicates that +the adapter does support scatter gather. + +SG_SET_RESERVED_SIZE +W: +This is not currently implemented. It is intended for reserving either a +large buffer or scatter gather list that will be available until the +current file descriptor is closed. The requested amount of memory may +not be available so SG_GET_RESERVED_SIZE should be used after this call +to see how much was reserved. (EBUSY error possible) + +SG_GET_RESERVED_SIZE +: +Assumes 3rd argument points to an int and places the size in bytes of +the DMA buffer reserved on open() for emergencies. If this is 0 then it +is probably not wise to attempt on operation like burning a CD on this +file descriptor. + +SG_SET_MERGE_FD +W: +Assumes 3rd argument is pointing to an int. 0 (the default) causes all +subsequent sequencing to be per file descriptor. 1 causes all subsequent +sequencing to be per device. If this command tries to change the current +state and the is one or more _other_ file descriptors using this sg +device then an EBUSY error occurs. Also if this file descriptor was not +open()ed with the O_RDWR flag then an EACCES error occurs. +Per device sequencing was the original semantics and allowed, for example +different processes to "share" the device, one perhaps write()ing with +the other one read()ing. This command is supplied if anyone needs those +semantics. Per file descriptor sequencing, perhaps with the usage of +the O_EXCL flag, seems more sensible. + +SG_GET_MERGE_FD +: +Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies +sequencing is per file descriptor. 1 implies sequencing is per device +(original sg driver's semantics). + +SG_SET_COMMAND_Q +: +Assumes 3rd argument is pointing to an int. 0 (current default, set by +SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write() +a packet while one is already queued will result in a EDOM error. +1 turns command queuing on. +Changing the queuing state only effects write()s done after the change. +Only the current file descriptor is effected by this command. + +SG_GET_COMMAND_Q +: +Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies +that command queuing is off on this file descriptor. 1 implies command +queuing is on. + +SG_SET_DEBUG +: +Assumes 3rd argument is pointing to an int. 0 (default) turns debugging +off. Values > 0 cause the SCSI sense buffer to be decoded and output +to the console/log when a SCSI device error occurs. Values > 8 cause +the current sg device driver's state to be output to the console/log +(this is a "one off" effect). +If you need a _lot_ of the SCSI sub-system debug information (mainly from +the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of +debug will appear in your console/log. + +ioctl (in common with sd, st + sr) +---------------------------------- +The following ioctl()s can be called from any high-level scsi device +driver (ie sd, st, sr + sg). Access permissions may differ a bit from +one device to another, the access information given below is specific to +the sg device driver. + +SCSI_IOCTL_GET_IDLUN: +SCSI_IOCTL_GET_BUS_NUMBER: + +SCSI_IOCTL_SEND_COMMAND: W +If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto +the SCSI mid-level driver for processing. +Don't know much about this one but it looks pretty powerful and +dangerous. Some comments says it is also deprecated. + +: W +If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto +the SCSI mid-level driver for processing. + + +poll +---- +This is a native call in Linux 2.2 but most of its capabilities are available +through the older select() call. Given a choice poll() should probably be +used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK +for polling; or alternatively with asynchronous notification using the +fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal. +Only if something drastically is wrong (eg file handle gone stale) will +POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set. +POLLIN is set when there is one or more packets waiting to be read. +When POLLIN is set it implies that a read() will not block (or yield +EAGAIN in non-blocking mode) but return a packet immediately. +POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet +(ie will _not_ yield an EDOM error). The setting of POLLOUT is effected +by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain +set until the number of queued packets reaches SG_MAX_QUEUE, if the +state is off then POLLOUT is only set when no packets are queued. +Note that a packet can be queued after write()ing but not available to be +read(); this typically happens when a SCSI read command is issued while +the data is being retreaved. +Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case +it is per device. + + +fcntl +----- +There are several uses for this system call in association with a sg +file descriptor. The first pseudo code shows code that is useful for +scanning the sg devices, taking care not to be caught in a wait for +an O_EXCL lock by another process, and when the appropriate device is +found switching to normal blocked io. A working example of this logic +is in the sg_scan.c utility program. + +open("/dev/sga", O_RDONLY | O_NONBLOCK) +/* check device, EBUSY means some other process has O_EXCL lock on it */ +/* one the device you want is found then ... */ +flags = fcntl(sg_fd, F_GETFL) +fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK)) +/* for simple apps is is easier to use normal blocked io */ + + +Some work has to be done in Linux to set up for asynchronous notification. +This is a non-blocking mode of operation in which when the driver receives +data back from a device so that a read() can be done, it sends a SIGPOLL +(aka SIGIO) signal to the owning process. A working example of this logic +is in the sg_poll.c test program. + +sigemptyset(&sig_set) +sigaddset(&sig_set, SIGPOLL) +sigaction(SIGPOLL, &s_action, 0) +fcntl(sg_fd, F_SETOWN, getpid()) +flags = fcntl(sg_fd, F_GETFL); +fcntl(sg_fd, F_SETFL, flags | O_ASYNC) + + +Utility and Test Programs +========================= diff -u --recursive --new-file v2.2.6/linux/MAINTAINERS linux/MAINTAINERS --- v2.2.6/linux/MAINTAINERS Fri Apr 16 14:47:30 1999 +++ linux/MAINTAINERS Sat Apr 24 18:23:38 1999 @@ -650,6 +650,11 @@ W: http://www.torque.net/sg S: Maintained +SCSI GENERIC +L: linux-scsi@vger.rutgers.edu +M: douglas.gilbert@rbcds.com +S: Maintained + SCSI SUBSYSTEM L: linux-scsi@vger.rutgers.edu S: Unmaintained @@ -698,7 +703,7 @@ P: Jakub Jelinek M: jj@sunsite.ms.mff.cuni.cz P: Anton Blanchard -M: anton@jubilex.progsoc.uts.edu.au +M: anton@progsoc.uts.edu.au L: sparclinux@vger.rutgers.edu L: ultralinux@vger.rutgers.edu W: http://ultra.linux.cz @@ -771,6 +776,20 @@ L: linux-kernel@vger.rutgers.edu S: Maintained +USB HUB AND UHCI DRIVERS +P: Johannes Erdfelt +M: jerdfelt@sventech.com +L: linux-usb@peloncho.fis.ucm.es +S: Maintained + +USB OHCI DRIVER +P: Gregory P. Smith +M: greg@electricrain.com +M: greg@suitenine.com +L: linux-usb@peloncho.fis.ucm.es +S: Maintained (not yet usable) +W: http://suitenine.com/usb/ + VFAT FILESYSTEM: P: Gordon Chaffee M: chaffee@cs.berkeley.edu @@ -784,9 +803,9 @@ W: http://roadrunner.swansea.linux.org.uk/v4l.shtml S: Maintained -WAN ROUTER AND SANGOMA WANPIPE DRIVERS (X.25, FRAME RELAY, PPP) -P: Gene Kozin -M: genek@compuserve.com +WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC) +P: Jaspreet Singh +M: jaspreet@sangoma.com M: dm@sangoma.com W: http://www.sangoma.com S: Supported diff -u --recursive --new-file v2.2.6/linux/Makefile linux/Makefile --- v2.2.6/linux/Makefile Fri Apr 16 14:47:30 1999 +++ linux/Makefile Mon Apr 26 12:24:24 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 6 +SUBLEVEL = 7 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -175,7 +175,7 @@ endif ifeq ($(CONFIG_USB),y) -DRIVERS := $(DRIVERS) drivers/uusbd/usb.a +DRIVERS := $(DRIVERS) drivers/usb/usb.a endif ifeq ($(CONFIG_I2O),y) diff -u --recursive --new-file v2.2.6/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.2.6/linux/arch/alpha/kernel/setup.c Tue Jan 19 11:32:50 1999 +++ linux/arch/alpha/kernel/setup.c Sat Apr 24 17:54:08 1999 @@ -183,6 +183,11 @@ vec = get_sysvec_byname(p+9); continue; } + + if (strncmp(p, "cycle=", 6) == 0) { + est_cycle_freq = simple_strtol(p+6, NULL, 0); + continue; + } } /* Replace the command line, not that we've killed it with strtok. */ @@ -721,8 +726,8 @@ (char*)cpu->serial_no, systype_name, sysvariation_name, hwrpb->sys_revision, (char*)hwrpb->ssn, - hwrpb->cycle_freq ? : est_cycle_freq, - hwrpb->cycle_freq ? "" : "est.", + est_cycle_freq ? : hwrpb->cycle_freq, + est_cycle_freq ? "est." : "", hwrpb->intr_freq / 4096, (100 * hwrpb->intr_freq / 4096) % 100, hwrpb->pagesize, diff -u --recursive --new-file v2.2.6/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.2.6/linux/arch/alpha/kernel/time.c Tue Mar 23 14:35:46 1999 +++ linux/arch/alpha/kernel/time.c Sat Apr 24 17:54:08 1999 @@ -18,6 +18,9 @@ * fixed tick loss calculation in timer_interrupt * (round system clock to nearest tick instead of truncating) * fixed algorithm in time_init for getting time from CMOS clock + * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) + * fixed algorithm in do_gettimeofday() for calculating the precise time + * from processor cycle counter (now taking lost_ticks into account) */ #include #include @@ -223,7 +226,7 @@ { void (*irq_handler)(int, void *, struct pt_regs *); unsigned int year, mon, day, hour, min, sec, cc1, cc2; - unsigned long cycle_freq; + unsigned long cycle_freq, diff, one_percent; /* * The Linux interpretation of the CMOS clock register contents: @@ -237,19 +240,30 @@ /* Read cycle counter exactly on falling edge of update flag */ cc1 = rpcc(); - /* If our cycle frequency isn't valid, go another round and give - a guess at what it should be. */ - cycle_freq = hwrpb->cycle_freq; - if (cycle_freq == 0) { - printk("HWRPB cycle frequency bogus. Estimating... "); - + if (!est_cycle_freq) { + /* Sometimes the hwrpb->cycle_freq value is bogus. + Go another round to check up on it and see. */ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); cc2 = rpcc(); - est_cycle_freq = cycle_freq = cc2 - cc1; + est_cycle_freq = cc2 - cc1; cc1 = cc2; + } - printk("%lu Hz\n", cycle_freq); + /* If the given value is within 1% of what we calculated, + accept it. Otherwise, use what we found. */ + cycle_freq = hwrpb->cycle_freq; + one_percent = cycle_freq / 100; + diff = cycle_freq - est_cycle_freq; + if (diff < 0) + diff = -diff; + if (diff > one_percent) { + cycle_freq = est_cycle_freq; + printk("HWRPB cycle frequency bogus. Estimated %lu Hz\n", + cycle_freq); + } + else { + est_cycle_freq = 0; } /* From John Bowman : allow the values @@ -314,8 +328,10 @@ void do_gettimeofday(struct timeval *tv) { - unsigned long flags, now, delta_cycles, delta_usec; + unsigned long flags, delta_cycles, delta_usec; unsigned long sec, usec; + __u32 now; + extern volatile unsigned long lost_ticks; /*kernel/sched.c*/ now = rpcc(); save_and_cli(flags); @@ -337,8 +353,14 @@ * with no clear gain. */ - delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625; + delta_usec = (delta_cycles * state.scaled_ticks_per_cycle + + state.partial_tick + + (lost_ticks << FIX_SHIFT) ) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; + + /* the 'lost_tics' term above implements this: + * delta_usec += lost_ticks * (1000000 / HZ); + */ usec += delta_usec; if (usec >= 1000000) { diff -u --recursive --new-file v2.2.6/linux/arch/alpha/lib/clear_user.S linux/arch/alpha/lib/clear_user.S --- v2.2.6/linux/arch/alpha/lib/clear_user.S Sun Nov 30 10:59:02 1997 +++ linux/arch/alpha/lib/clear_user.S Sat Apr 24 17:54:08 1999 @@ -80,6 +80,7 @@ ret $31, ($28), 1 # .. e1 : __do_clear_user: + ldgp $29,0($27) # we do exceptions -- we need the gp. and $6, 7, $4 # e0 : find dest misalignment beq $0, $zerolength # .. e1 : addq $0, $4, $1 # e0 : bias counter diff -u --recursive --new-file v2.2.6/linux/arch/alpha/lib/copy_user.S linux/arch/alpha/lib/copy_user.S --- v2.2.6/linux/arch/alpha/lib/copy_user.S Sat May 2 14:19:52 1998 +++ linux/arch/alpha/lib/copy_user.S Sat Apr 24 17:54:08 1999 @@ -46,6 +46,8 @@ .globl __copy_user .ent __copy_user __copy_user: + ldgp $29,0($27) # we do exceptions -- we need the gp. + .prologue 1 and $6,7,$3 beq $0,$35 beq $3,$36 diff -u --recursive --new-file v2.2.6/linux/arch/alpha/lib/strlen_user.S linux/arch/alpha/lib/strlen_user.S --- v2.2.6/linux/arch/alpha/lib/strlen_user.S Wed Jun 24 22:54:03 1998 +++ linux/arch/alpha/lib/strlen_user.S Sat Apr 24 17:54:08 1999 @@ -27,7 +27,8 @@ .align 3 __strlen_user: - .prologue 0 + ldgp $29,0($27) # we do exceptions -- we need the gp. + .prologue 1 EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned) lda t1, -1(zero) diff -u --recursive --new-file v2.2.6/linux/arch/alpha/lib/strncpy_from_user.S linux/arch/alpha/lib/strncpy_from_user.S --- v2.2.6/linux/arch/alpha/lib/strncpy_from_user.S Thu Feb 6 04:48:45 1997 +++ linux/arch/alpha/lib/strncpy_from_user.S Sat Apr 24 17:54:08 1999 @@ -31,6 +31,7 @@ .globl __strncpy_from_user .ent __strncpy_from_user .frame $30, 0, $26 + .prologue 1 .align 3 $aligned: @@ -99,6 +100,7 @@ /*** The Function Entry Point ***/ .align 3 __strncpy_from_user: + ldgp $29, 0($27) # we do exceptions -- we need the gp. mov a0, v0 # save the string start beq a2, $zerolength diff -u --recursive --new-file v2.2.6/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.2.6/linux/arch/i386/config.in Tue Feb 23 15:21:32 1999 +++ linux/arch/i386/config.in Mon Apr 26 13:49:17 1999 @@ -168,6 +168,8 @@ source drivers/char/Config.in +# source drivers/usb/Config.in + source fs/Config.in if [ "$CONFIG_VT" = "y" ]; then diff -u --recursive --new-file v2.2.6/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.2.6/linux/arch/i386/kernel/bios32.c Tue Mar 23 14:35:46 1999 +++ linux/arch/i386/kernel/bios32.c Sat Apr 24 17:49:37 1999 @@ -1095,6 +1095,8 @@ * for buggy PCI BIOS'es :-[). */ +extern int skip_ioapic_setup; + static void __init pcibios_fixup_devices(void) { struct pci_dev *dev; @@ -1147,6 +1149,7 @@ /* * Recalculate IRQ numbers if we use the I/O APIC */ + if(!skip_ioapic_setup) { int irq; unsigned char pin; diff -u --recursive --new-file v2.2.6/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.2.6/linux/arch/i386/kernel/smp.c Fri Apr 16 14:47:30 1999 +++ linux/arch/i386/kernel/smp.c Thu Apr 22 19:24:50 1999 @@ -29,6 +29,7 @@ * from Jose Renau * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites + * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. */ #include @@ -1707,9 +1708,8 @@ system=1; irq_enter(cpu, 0); + update_one_process(p, 1, user, system, cpu); if (p->pid) { - update_one_process(p, 1, user, system, cpu); - p->counter -= 1; if (p->counter < 0) { p->counter = 0; @@ -1722,7 +1722,6 @@ kstat.cpu_user += user; kstat.per_cpu_user[cpu] += user; } - kstat.cpu_system += system; kstat.per_cpu_system[cpu] += system; diff -u --recursive --new-file v2.2.6/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c --- v2.2.6/linux/arch/m68k/atari/atakeyb.c Wed Jan 20 23:14:04 1999 +++ linux/arch/m68k/atari/atakeyb.c Mon Apr 26 13:35:34 1999 @@ -291,7 +291,7 @@ atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL; add_timer( &atakeyb_rep_timer ); - handle_scancode(rep_scancode); + handle_scancode(rep_scancode, 1); } atari_enable_irq( IRQ_MFP_ACIA ); @@ -448,7 +448,7 @@ add_timer( &atakeyb_rep_timer ); } - handle_scancode(break_flag | scancode); + handle_scancode(scancode, !break_flag); break; } break; diff -u --recursive --new-file v2.2.6/linux/arch/m68k/hp300/hil.c linux/arch/m68k/hp300/hil.c --- v2.2.6/linux/arch/m68k/hp300/hil.c Sat Sep 5 16:46:40 1998 +++ linux/arch/m68k/hp300/hil.c Mon Apr 26 13:37:14 1999 @@ -223,12 +223,13 @@ { case 0x40: { - unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0); + int down = (poll.data[1] & 1) == 0; + unsigned char scode = poll.data[1] >> 1; #if 0 - if (scode & 0x80) - printk("[%02x]", scode & 0x7f); + if (down) + printk("[%02x]", scode); #endif - handle_scancode(scode); + handle_scancode(scode, down); } break; } diff -u --recursive --new-file v2.2.6/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c --- v2.2.6/linux/arch/m68k/mac/mackeyb.c Wed Jan 20 23:14:04 1999 +++ linux/arch/m68k/mac/mackeyb.c Mon Apr 26 13:38:03 1999 @@ -60,7 +60,7 @@ extern struct kbd_struct kbd_table[]; extern void adb_bus_init(void); -extern void handle_scancode(unsigned char); +extern void handle_scancode(unsigned char, int); extern void put_queue(int); /* keyb */ @@ -387,7 +387,7 @@ */ switch (keycode) { case 0x39: - handle_scancode(keycode); /* down */ + handle_scancode(keycode, 1); /* down */ up_flag = 0x80; /* see below ... */ mark_bh(KEYBOARD_BH); break; @@ -397,7 +397,7 @@ } } - handle_scancode(keycode + up_flag); + handle_scancode(keycode, !up_flag); } static void diff -u --recursive --new-file v2.2.6/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.2.6/linux/arch/sparc/defconfig Tue Mar 23 14:35:46 1999 +++ linux/arch/sparc/defconfig Thu Apr 22 19:24:51 1999 @@ -261,6 +261,8 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S --- v2.2.6/linux/arch/sparc/kernel/entry.S Tue Mar 23 14:35:46 1999 +++ linux/arch/sparc/kernel/entry.S Wed Apr 28 08:47:39 1999 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.157 1999/01/19 07:54:32 davem Exp $ +/* $Id: entry.S,v 1.158 1999/04/27 14:35:07 davem Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -874,7 +874,7 @@ ! We want error in %l5, vaddr in %l6 sun4c_fault: #ifdef CONFIG_SUN4 - sethi C_LABEL(sun4c_memerr_reg), %l4 + sethi %hi(C_LABEL(sun4c_memerr_reg)), %l4 ld [%l4+%lo(C_LABEL(sun4c_memerr_reg))], %l4 ! memerr ctrl reg addr ld [%l4], %l6 ! memerr ctrl reg ld [%l4 + 4], %l5 ! memerr vaddr reg @@ -956,7 +956,7 @@ sll %l6, 2, %l6 ld [%l4 + %l6], %l4 #ifdef CONFIG_SUN4 - sethi PAGE_MASK, %l6 + sethi %hi(PAGE_MASK), %l6 andcc %l4, %l6, %g0 #else andcc %l4, PAGE_MASK, %g0 @@ -1117,7 +1117,7 @@ #ifndef CONFIG_SUN4 and %l4, PAGE_MASK, %l4 #else - sethi PAGE_MASK, %l6 + sethi %hi(PAGE_MASK), %l6 and %l4, %l6, %l4 #endif diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v2.2.6/linux/arch/sparc/kernel/head.S Tue Mar 23 14:35:46 1999 +++ linux/arch/sparc/kernel/head.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.93 1999/01/10 06:03:14 jj Exp $ +/* $Id: head.S,v 1.95 1999/04/13 07:40:34 anton Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -408,13 +408,11 @@ /* This was the only reasonable way I could think of to properly align * these page-table data structures. */ - .globl C_LABEL(bootup_user_stack) .globl C_LABEL(pg0), C_LABEL(pg1), C_LABEL(pg2), C_LABEL(pg3) .globl C_LABEL(empty_bad_page) .globl C_LABEL(empty_bad_page_table) .globl C_LABEL(empty_zero_page) .globl C_LABEL(swapper_pg_dir) -C_LABEL(bootup_user_stack): .skip 0x2000 C_LABEL(swapper_pg_dir): .skip PAGE_SIZE C_LABEL(pg0): .skip PAGE_SIZE C_LABEL(pg1): .skip PAGE_SIZE @@ -427,8 +425,8 @@ .global C_LABEL(root_flags) .global C_LABEL(ram_flags) .global C_LABEL(root_dev) - .global C_LABEL(ramdisk_image) - .global C_LABEL(ramdisk_size) + .global C_LABEL(sparc_ramdisk_image) + .global C_LABEL(sparc_ramdisk_size) /* This stuff has to be in sync with SILO and other potential boot loaders * Fields should be kept upward compatible and whenever any change is made, @@ -443,9 +441,9 @@ .half 0 C_LABEL(ram_flags): .half 0 -C_LABEL(ramdisk_image): +C_LABEL(sparc_ramdisk_image): .word 0 -C_LABEL(ramdisk_size): +C_LABEL(sparc_ramdisk_size): .word 0 .word C_LABEL(reboot_command) @@ -1005,8 +1003,8 @@ WRITE_PAUSE /* I want a kernel stack NOW! */ - set C_LABEL(bootup_user_stack), %g1 - set (0x2000 - REGWIN_SZ), %g2 + set C_LABEL(init_task_union), %g1 + set (TASK_UNION_SIZE - REGWIN_SZ), %g2 add %g1, %g2, %sp mov 0, %fp /* And for good luck */ diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.2.6/linux/arch/sparc/kernel/irq.c Sun Nov 8 14:02:45 1998 +++ linux/arch/sparc/kernel/irq.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.91 1998/10/14 07:04:17 jj Exp $ +/* $Id: irq.c,v 1.93 1999/04/21 06:15:45 anton Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -8,7 +8,7 @@ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) - * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -192,12 +194,18 @@ restore_flags(flags); } -/* Per-processor IRQ and bh locking depth, both SMP and non-SMP code use this. */ +#ifndef __SMP__ +unsigned int local_bh_count; +unsigned int local_irq_count; + +#else +/* SMP interrupt locking on Sparc. */ + unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; -#ifdef __SMP__ -/* SMP interrupt locking on Sparc. */ +atomic_t global_bh_lock = ATOMIC_INIT(0); +spinlock_t global_bh_count = SPIN_LOCK_UNLOCKED; /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -208,58 +216,71 @@ /* Global IRQ locking depth. */ atomic_t global_irq_count = ATOMIC_INIT(0); -atomic_t global_bh_count = ATOMIC_INIT(0); -atomic_t global_bh_lock = ATOMIC_INIT(0); - /* This protects BH software state (masks, things like that). */ spinlock_t sparc_bh_lock = SPIN_LOCK_UNLOCKED; -#ifdef DEBUG_IRQLOCK +void smp_show_backtrace_all_cpus(void); +void show_backtrace(void); -#undef INIT_STUCK -#define INIT_STUCK 100000000 +#define MAXCOUNT 100000000 +#define VERBOSE_DEBUG_IRQLOCK -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("wait_on_bh CPU#%d stuck at %08lx\n", cpu, where); stuck = INIT_STUCK; } - -static inline void wait_on_bh(int cpu, unsigned long where) +static void show(char * str) { - int stuck = INIT_STUCK; - do { - STUCK; - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} + int i; + int cpu = smp_processor_id(); + + printk("\n%s, CPU %d:\n", str, cpu); + printk("irq: %d [ ", atomic_read(&global_irq_count)); -static unsigned long previous_irqholder; + for (i = 0; i < NR_CPUS; i++) { + printk("%d ", local_irq_count[i]); + } + printk("]\n"); -#undef INIT_STUCK -#define INIT_STUCK 100000000 + printk("bh: %d [ ", (spin_is_locked(&global_bh_count) ? 1 : 0)); -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; } + for (i = 0; i < NR_CPUS; i++) { + printk("%d ", local_bh_count[cpu]); + } + printk("]\n"); + +#ifdef VERBOSE_DEBUG_IRQLOCK + smp_show_backtrace_all_cpus(); +#else + show_backtrace(); +#endif +} + +static inline void wait_on_bh(void) +{ + int count = MAXCOUNT; + do { + if(!--count) { + show("wait_on_bh"); + count = 0; + } + barrier(); + } while(spin_is_locked(&global_bh_count)); +} /* * We have to allow irqs to arrive between __sti and __cli */ -#define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +#define SYNC_OTHER_CORES(x) udelay(x+1) -static inline void wait_on_irq(int cpu, unsigned long where) +static inline void wait_on_irq(int cpu) { - int stuck = INIT_STUCK; - int local_count = local_irq_count[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 (local_bh_count[cpu] || !atomic_read(&global_bh_count)) + if (local_bh_count[cpu] || !spin_is_locked(&global_bh_count)) break; } @@ -267,17 +288,18 @@ spin_unlock(&global_irq_lock); for (;;) { - STUCK; - + if (!--count) { + show("wait_on_irq"); + count = ~0; + } __sti(); SYNC_OTHER_CORES(cpu); __cli(); - if (atomic_read(&global_irq_count)) continue; - if (*((unsigned char *)&global_irq_lock)) + if (spin_is_locked (&global_irq_lock)) continue; - if (!local_bh_count[cpu] && atomic_read(&global_bh_count)) + if (!local_bh_count[cpu] && spin_is_locked(&global_bh_count)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -295,14 +317,8 @@ */ void synchronize_bh(void) { - unsigned long where; - - __asm__("mov %%i7, %0" : "=r" (where)); - - if (atomic_read(&global_bh_count) && !in_interrupt()) { - int cpu = smp_processor_id(); - wait_on_bh(cpu, where); - } + if (spin_is_locked (&global_bh_count) && !in_interrupt()) + wait_on_bh(); } /* @@ -321,16 +337,9 @@ } } -#undef INIT_STUCK -#define INIT_STUCK 10000000 - -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;} - -static inline void get_irqlock(int cpu, unsigned long where) +static inline void get_irqlock(int cpu) { - int stuck = INIT_STUCK; + int count = MAXCOUNT; if (!spin_trylock(&global_irq_lock)) { /* do we already hold the lock? */ @@ -338,23 +347,25 @@ return; /* Uhhuh.. Somebody else got it. Wait.. */ do { - do { - STUCK; + while (spin_is_locked(&global_irq_lock)) { + if (!--count) { + show("get_irqlock"); + count = ~0; + } barrier(); - } while (*((volatile unsigned char *)&global_irq_lock)); + } } while (!spin_trylock(&global_irq_lock)); } /* * We also to make sure that nobody else is running * in an interrupt context. */ - wait_on_irq(cpu, where); + wait_on_irq(cpu); /* * Ok, finally.. */ global_irq_holder = cpu; - previous_irqholder = where; } /* @@ -372,9 +383,6 @@ void __global_cli(void) { unsigned int flags; - unsigned long where; - - __asm__("mov %%i7, %0" : "=r" (where)); __save_flags(flags); @@ -382,7 +390,7 @@ int cpu = smp_processor_id(); __cli(); if (!local_irq_count[cpu]) - get_irqlock(cpu, where); + get_irqlock(cpu); } } @@ -442,65 +450,14 @@ __sti(); break; default: - printk("global_restore_flags: %08lx (%08lx)\n", - flags, (&flags)[-1]); + { + unsigned long pc; + __asm__ __volatile__("mov %%i7, %0" : "=r" (pc)); + printk("global_restore_flags: Bogon flags(%08lx) caller %08lx\n", flags, pc); } -} - -#undef INIT_STUCK -#define INIT_STUCK 200000000 - -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;} - -#define VERBOSE_IRQLOCK_DEBUGGING - -void irq_enter(int cpu, int irq, void *_opaque) -{ -#ifdef VERBOSE_IRQLOCK_DEBUGGING - extern void smp_show_backtrace_all_cpus(void); -#endif - int stuck = INIT_STUCK; - - hardirq_enter(cpu); - barrier(); - while (*((volatile unsigned char *)&global_irq_lock)) { - if ((unsigned char) cpu == global_irq_holder) { - struct pt_regs *regs = _opaque; - int sbh_cnt = atomic_read(&global_bh_count); - int globl_locked = *((unsigned char *)&global_irq_lock); - int globl_icount = atomic_read(&global_irq_count); - int local_count = local_irq_count[cpu]; - unsigned long pc = regs->pc; - - /* It is very important that we load the state variables - * before we do the first call to printk() as printk() - * could end up changing them... - */ - - printk("CPU[%d]: BAD! Local IRQ's enabled, global disabled " - "interrupt at PC[%08lx]\n", cpu, pc); - printk("CPU[%d]: bhcnt[%d] glocked[%d] gicnt[%d] licnt[%d]\n", - cpu, sbh_cnt, globl_locked, globl_icount, local_count); -#ifdef VERBOSE_IRQLOCK_DEBUGGING - printk("Performing backtrace on all cpus, write this down!\n"); - smp_show_backtrace_all_cpus(); -#endif - break; - } - STUCK; - barrier(); } } -void irq_exit(int cpu, int irq) -{ - hardirq_exit(cpu); - release_irqlock(cpu); -} - -#endif /* DEBUG_IRQLOCK */ #endif /* __SMP__ */ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) @@ -542,7 +499,7 @@ smp4m_irq_rotate(cpu); #endif #endif - irq_enter(cpu, irq, regs); + irq_enter(cpu, irq); action = *(irq + irq_action); kstat.irqs[cpu][irq]++; do { @@ -563,7 +520,7 @@ int cpu = smp_processor_id(); disable_pil_irq(irq); - irq_enter(cpu, irq, regs); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; floppy_interrupt(irq, dev_id, regs); irq_exit(cpu, irq); diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.2.6/linux/arch/sparc/kernel/process.c Mon Mar 29 11:09:11 1999 +++ linux/arch/sparc/kernel/process.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.133 1999/03/24 11:42:30 davem Exp $ +/* $Id: process.c,v 1.136 1999/04/16 01:20:33 anton Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -205,8 +205,10 @@ int cpu = smp_processor_id(); spin_lock_irqsave(&sparc_backtrace_lock, flags); - rw = (struct reg_window *) fp; - while(rw) { + + rw = (struct reg_window *)fp; + while(rw && (((unsigned long) rw) >= PAGE_OFFSET) && + !(((unsigned long) rw) & 0x7)) { printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] " "FP[%08lx] CALLER[%08lx]\n", cpu, rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3], @@ -218,28 +220,21 @@ spin_unlock_irqrestore(&sparc_backtrace_lock, flags); } +#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t") +#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t") +#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp)) + void show_backtrace(void) { unsigned long fp; - __asm__ __volatile__( - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "save %%sp, -64, %%sp\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "restore\n\t" - "mov %%i6, %0" : "=r" (fp)); + __SAVE; __SAVE; __SAVE; __SAVE; + __SAVE; __SAVE; __SAVE; __SAVE; + __RESTORE; __RESTORE; __RESTORE; __RESTORE; + __RESTORE; __RESTORE; __RESTORE; __RESTORE; + + __GET_FP(fp); + __show_backtrace(fp); } @@ -381,8 +376,21 @@ current->tss.current_ds = USER_DS; if (current->tss.flags & SPARC_FLAG_KTHREAD) { current->tss.flags &= ~SPARC_FLAG_KTHREAD; - switch_to_context(current); + + /* We must fixup kregs as well. */ + current->tss.kregs = (struct pt_regs *) + (((unsigned long)current) + + (TASK_UNION_SIZE - TRACEREG_SZ)); } + + /* Exec'ing out of a vfork() shared address space is + * tricky on sparc32. exec_mmap will not set the mmu + * context because it sets the new current->mm after + * calling init_new_context and activate_context is + * a nop on sparc32, so we gotta catch it here. And + * clone()'s had the same problem. -DaveM + */ + switch_to_context(current); } static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src) @@ -514,9 +522,11 @@ p->tss.kpsr = current->tss.fork_kpsr; #endif p->tss.kwim = current->tss.fork_kwim; - p->tss.kregs = childregs; if(regs->psr & PSR_PS) { + extern struct pt_regs fake_swapper_regs; + + p->tss.kregs = &fake_swapper_regs; new_stack = (struct reg_window *) ((((unsigned long)p) + (TASK_UNION_SIZE)) - @@ -529,6 +539,7 @@ sizeof(struct reg_window)); childregs->u_regs[UREG_G6] = (unsigned long) p; } else { + p->tss.kregs = childregs; childregs->u_regs[UREG_FP] = sp; p->tss.flags &= ~SPARC_FLAG_KTHREAD; p->tss.current_ds = USER_DS; diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.2.6/linux/arch/sparc/kernel/setup.c Mon Oct 5 13:13:37 1998 +++ linux/arch/sparc/kernel/setup.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.103 1998/09/21 05:05:23 jj Exp $ +/* $Id: setup.c,v 1.105 1999/04/13 14:17:08 jj Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -271,8 +271,8 @@ extern unsigned short root_flags; extern unsigned short root_dev; extern unsigned short ram_flags; -extern unsigned ramdisk_image; -extern unsigned ramdisk_size; +extern unsigned sparc_ramdisk_image; +extern unsigned sparc_ramdisk_size; #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 @@ -285,7 +285,7 @@ struct tt_entry *sparc_ttable; -static struct pt_regs fake_swapper_regs = { 0, 0, 0, 0, { 0, } }; +struct pt_regs fake_swapper_regs = { 0, 0, 0, 0, { 0, } }; static void prom_cons_write(struct console *con, const char *str, unsigned count) { @@ -375,7 +375,7 @@ sun4c_probe_vac(); load_mmu(); total = prom_probe_memory(); - *memory_start_p = (((unsigned long) &end)); + *memory_start_p = PAGE_ALIGN(((unsigned long) &end)); if(!packed) { for(i=0; sp_banks[i].num_bytes != 0; i++) { @@ -404,10 +404,10 @@ rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif #ifdef CONFIG_BLK_DEV_INITRD - if (ramdisk_image) { - initrd_start = ramdisk_image; + if (sparc_ramdisk_image) { + initrd_start = sparc_ramdisk_image; if (initrd_start < KERNBASE) initrd_start += KERNBASE; - initrd_end = initrd_start + ramdisk_size; + initrd_end = initrd_start + sparc_ramdisk_size; if (initrd_end > *memory_end_p) { printk(KERN_CRIT "initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", @@ -417,6 +417,14 @@ if (initrd_start >= *memory_start_p && initrd_start < *memory_start_p + 2 * PAGE_SIZE) { initrd_below_start_ok = 1; *memory_start_p = PAGE_ALIGN (initrd_end); + } else if (initrd_start && sparc_ramdisk_image < KERNBASE) { + switch (sparc_cpu_model) { + case sun4m: + case sun4d: + initrd_start -= KERNBASE; + initrd_end -= KERNBASE; + break; + } } } #endif diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- v2.2.6/linux/arch/sparc/kernel/sun4d_irq.c Sun Nov 8 14:02:45 1998 +++ linux/arch/sparc/kernel/sun4d_irq.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.17 1998/10/18 03:31:03 davem Exp $ +/* $Id: sun4d_irq.c,v 1.18 1999/04/20 13:22:30 anton Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * @@ -193,7 +193,7 @@ cc_set_iclr(1 << irq); - irq_enter(cpu, irq, regs); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; if (!sbusl) { action = *(irq + irq_action); diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c --- v2.2.6/linux/arch/sparc/kernel/sun4m_irq.c Mon Oct 5 13:13:37 1998 +++ linux/arch/sparc/kernel/sun4m_irq.c Thu Apr 22 19:24:51 1999 @@ -253,7 +253,7 @@ /* Map the per-cpu Counter registers. */ sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0, - PAGE_SIZE*NCPUS, "counters_percpu", + PAGE_SIZE*SUN4M_NCPUS, "counters_percpu", cnt_regs[0].which_io, 0x0); /* Map the system Counter register. */ @@ -334,7 +334,7 @@ /* Map the interrupt registers for all possible cpus. */ sun4m_interrupts = sparc_alloc_io(int_regs[0].phys_addr, 0, - PAGE_SIZE*NCPUS, "interrupts_percpu", + PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu", int_regs[0].which_io, 0x0); /* Map the system interrupt control registers. */ diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.2.6/linux/arch/sparc/kernel/sun4m_smp.c Thu Nov 19 09:56:27 1998 +++ linux/arch/sparc/kernel/sun4m_smp.c Thu Apr 22 19:24:51 1999 @@ -448,6 +448,7 @@ if(!--prof_counter[cpu]) { int user = user_mode(regs); + irq_enter(cpu, 0); if(current->pid) { update_one_process(current, 1, user, !user, cpu); @@ -456,7 +457,6 @@ current->need_resched = 1; } - spin_lock(&ticker_lock); if(user) { if(current->priority < DEF_PRIORITY) { kstat.cpu_nice++; @@ -469,9 +469,9 @@ kstat.cpu_system++; kstat.per_cpu_system[cpu]++; } - spin_unlock(&ticker_lock); } prof_counter[cpu] = prof_multiplier[cpu]; + irq_exit(cpu, 0); } } diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S --- v2.2.6/linux/arch/sparc/kernel/systbls.S Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc/kernel/systbls.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.82 1999/03/20 22:01:59 davem Exp $ +/* $Id: systbls.S,v 1.83 1999/04/07 17:14:06 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -25,7 +25,7 @@ /*30*/ .long sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice /*35*/ .long sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile /*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall -/*45*/ .long sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid +/*45*/ .long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl /*55*/ .long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve /*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize @@ -47,7 +47,7 @@ /*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit /*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall -/*155*/ .long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount +/*155*/ .long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall /*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall /*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents @@ -129,7 +129,7 @@ /*150*/ .long sys_getsockname, sunos_nosys, sunos_nosys .long sys_poll, sunos_nosys, sunos_nosys .long sunos_getdirentries, sys_statfs, sys_fstatfs - .long sys_umount, sunos_nosys, sunos_nosys + .long sys_oldumount, sunos_nosys, sunos_nosys .long sys_getdomainname, sys_setdomainname .long sunos_nosys, sys_quotactl, sunos_nosys .long sunos_mount, sys_ustat, sunos_semsys diff -u --recursive --new-file v2.2.6/linux/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c --- v2.2.6/linux/arch/sparc/kernel/unaligned.c Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/unaligned.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.17 1997/04/11 00:42:08 davem Exp $ +/* $Id: unaligned.c,v 1.18 1999/04/03 11:36:17 anton Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -332,7 +332,6 @@ enum direction dir = decode_direction(insn); int size = decode_access_size(insn); - lock_kernel(); if(!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel at <%08lx>.\n", regs->pc); @@ -380,7 +379,6 @@ } advance(regs); } - unlock_kernel(); } static inline int ok_for_user(struct pt_regs *regs, unsigned int insn, diff -u --recursive --new-file v2.2.6/linux/arch/sparc/lib/atomic.S linux/arch/sparc/lib/atomic.S --- v2.2.6/linux/arch/sparc/lib/atomic.S Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc/lib/atomic.S Thu Apr 22 19:24:51 1999 @@ -44,6 +44,7 @@ .globl ___atomic_add ___atomic_add: rd %psr, %g3 ! Keep the code small, old way was stupid + nop; nop; nop; ! Let the bits set or %g3, PSR_PIL, %g7 ! Disable interrupts wr %g7, 0x0, %psr ! Set %psr nop; nop; nop; ! Let the bits set @@ -69,6 +70,7 @@ .globl ___atomic_sub ___atomic_sub: rd %psr, %g3 ! Keep the code small, old way was stupid + nop; nop; nop; ! Let the bits set or %g3, PSR_PIL, %g7 ! Disable interrupts wr %g7, 0x0, %psr ! Set %psr nop; nop; nop; ! Let the bits set diff -u --recursive --new-file v2.2.6/linux/arch/sparc/lib/bitops.S linux/arch/sparc/lib/bitops.S --- v2.2.6/linux/arch/sparc/lib/bitops.S Sun Nov 8 14:02:45 1998 +++ linux/arch/sparc/lib/bitops.S Thu Apr 22 19:24:51 1999 @@ -20,12 +20,10 @@ .globl ___set_bit ___set_bit: rd %psr, %g3 - andcc %g3, PSR_PIL, %g0 - bne 1f - nop - wr %g3, PSR_PIL, %psr + nop; nop; nop; + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr nop; nop; nop -1: #ifdef __SMP__ set C_LABEL(bitops_spinlock), %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. @@ -38,17 +36,12 @@ #ifdef __SMP__ st %g5, [%g1] set C_LABEL(bitops_spinlock), %g5 - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g0, [%g5] + stb %g0, [%g5] #else - andcc %g3, PSR_PIL, %g0 - bne 1f - st %g5, [%g1] + st %g5, [%g1] #endif wr %g3, 0x0, %psr nop; nop; nop -1: jmpl %o7, %g0 mov %g4, %o7 @@ -56,12 +49,10 @@ .globl ___clear_bit ___clear_bit: rd %psr, %g3 - andcc %g3, PSR_PIL, %g0 - bne 1f - nop - wr %g3, PSR_PIL, %psr nop; nop; nop -1: + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop #ifdef __SMP__ set C_LABEL(bitops_spinlock), %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. @@ -74,17 +65,12 @@ #ifdef __SMP__ st %g5, [%g1] set C_LABEL(bitops_spinlock), %g5 - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g0, [%g5] + stb %g0, [%g5] #else - andcc %g3, PSR_PIL, %g0 - bne 1f - st %g5, [%g1] + st %g5, [%g1] #endif wr %g3, 0x0, %psr nop; nop; nop -1: jmpl %o7, %g0 mov %g4, %o7 @@ -92,12 +78,10 @@ .globl ___change_bit ___change_bit: rd %psr, %g3 - andcc %g3, PSR_PIL, %g0 - bne 1f - nop - wr %g3, PSR_PIL, %psr nop; nop; nop -1: + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop #ifdef __SMP__ set C_LABEL(bitops_spinlock), %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. @@ -110,17 +94,12 @@ #ifdef __SMP__ st %g5, [%g1] set C_LABEL(bitops_spinlock), %g5 - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g0, [%g5] + stb %g0, [%g5] #else - andcc %g3, PSR_PIL, %g0 - bne 1f - st %g5, [%g1] + st %g5, [%g1] #endif wr %g3, 0x0, %psr nop; nop; nop -1: jmpl %o7, %g0 mov %g4, %o7 @@ -128,12 +107,10 @@ .globl ___set_le_bit ___set_le_bit: rd %psr, %g3 - andcc %g3, PSR_PIL, %g0 - bne 1f - nop - wr %g3, PSR_PIL, %psr nop; nop; nop -1: + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop #ifdef __SMP__ set C_LABEL(bitops_spinlock), %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. @@ -146,29 +123,22 @@ #ifdef __SMP__ stb %g5, [%g1] set C_LABEL(bitops_spinlock), %g5 - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g0, [%g5] + stb %g0, [%g5] #else - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g5, [%g1] + stb %g5, [%g1] #endif wr %g3, 0x0, %psr nop; nop; nop -1: jmpl %o7, %g0 mov %g4, %o7 .globl ___clear_le_bit ___clear_le_bit: rd %psr, %g3 - andcc %g3, PSR_PIL, %g0 - bne 1f - nop - wr %g3, PSR_PIL, %psr nop; nop; nop -1: + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop #ifdef __SMP__ set C_LABEL(bitops_spinlock), %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. @@ -181,16 +151,11 @@ #ifdef __SMP__ stb %g5, [%g1] set C_LABEL(bitops_spinlock), %g5 - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g0, [%g5] + stb %g0, [%g5] #else - andcc %g3, PSR_PIL, %g0 - bne 1f - stb %g5, [%g1] + stb %g5, [%g1] #endif wr %g3, 0x0, %psr nop; nop; nop -1: jmpl %o7, %g0 mov %g4, %o7 diff -u --recursive --new-file v2.2.6/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c --- v2.2.6/linux/arch/sparc/lib/debuglocks.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc/lib/debuglocks.c Thu Apr 22 19:24:51 1999 @@ -1,12 +1,13 @@ -/* $Id: debuglocks.c,v 1.6 1999/02/23 13:23:55 jj Exp $ +/* $Id: debuglocks.c,v 1.7 1999/04/21 02:26:58 anton Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include #include +#include /* For NR_CPUS */ #include #include #include @@ -39,20 +40,22 @@ { int cpu = smp_processor_id(); - printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str, lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } static inline void show_write(char *str, rwlock_t *lock, unsigned long caller) { int cpu = smp_processor_id(); + int i; - printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx) reader[0]=%08lx reader[1]=%08lx reader[2]=%08lx reader[3]=%08lx\n", - str, lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3, - lock->reader_pc[0], - lock->reader_pc[1], - lock->reader_pc[2], - lock->reader_pc[3]); + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); + + for(i = 0; i < NR_CPUS; i++) + printk(" reader[i]=%08lx", lock->reader_pc[i]); + + printk("\n"); } #undef INIT_STUCK @@ -105,9 +108,6 @@ lock->lock = 0; } -#undef INIT_STUCK -#define INIT_STUCK 100000000 - void _do_read_lock(rwlock_t *rw, char *str) { unsigned long caller; @@ -135,9 +135,6 @@ rw->lock++; } -#undef INIT_STUCK -#define INIT_STUCK 100000000 - void _do_read_unlock(rwlock_t *rw, char *str) { unsigned long caller; @@ -164,9 +161,6 @@ barrier(); rw->lock -= 0x1ff; } - -#undef INIT_STUCK -#define INIT_STUCK 100000000 void _do_write_lock(rwlock_t *rw, char *str) { diff -u --recursive --new-file v2.2.6/linux/arch/sparc/lib/irqlock.S linux/arch/sparc/lib/irqlock.S --- v2.2.6/linux/arch/sparc/lib/irqlock.S Tue May 13 22:41:03 1997 +++ linux/arch/sparc/lib/irqlock.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: irqlock.S,v 1.4 1997/05/01 02:26:54 davem Exp $ +/* $Id: irqlock.S,v 1.5 1999/04/20 13:22:37 anton Exp $ * irqlock.S: High performance IRQ global locking and interrupt entry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -9,69 +9,6 @@ .text .align 4 - - /* This is incredibly insane... */ - .globl ___irq_enter -___irq_enter: - sethi %hi(local_irq_count), %g2 - sll %g1, 2, %g1 - or %g2, %lo(local_irq_count), %g2 - ld [%g2 + %g1], %g3 - sethi %hi(global_irq_count), %g5 - add %g3, 1, %g3 - or %g5, %lo(global_irq_count), %g5 - st %g3, [%g2 + %g1] -1: - ldstub [%g5 + 3], %g2 - orcc %g2, 0x0, %g0 - bne 1b - ld [%g5], %g3 - sra %g3, 8, %g3 - add %g3, 1, %g3 - sll %g3, 8, %g3 - st %g3, [%g5] - sethi %hi(global_irq_lock), %g1 - ldub [%g1 + %lo(global_irq_lock)], %g2 -1: - orcc %g2, 0x0, %g0 - bne,a 1b - ldub [%g1 + %lo(global_irq_lock)], %g2 -___irq_enter_out: - jmpl %o7, %g0 - mov %g4, %o7 - - .globl ___irq_exit -___irq_exit: - rd %psr, %g3 - sethi %hi(global_irq_count), %g1 - or %g3, PSR_PIL, %g3 - or %g1, %lo(global_irq_count), %g1 - wr %g3, 0x0, %psr - sethi %hi(local_irq_count), %g2 - sll %g7, 2, %g7 - or %g2, %lo(local_irq_count), %g2 - ld [%g2 + %g7], %g3 -1: - ldstub [%g1 + 3], %g5 - orcc %g5, 0x0, %g0 - bne 1b - ld [%g1], %g5 - sra %g5, 8, %g5 - sub %g5, 1, %g5 - sll %g5, 8, %g5 - st %g5, [%g1] - sub %g3, 1, %g3 - sethi %hi(global_irq_holder), %g1 - st %g3, [%g2 + %g7] - srl %g7, 2, %g7 - ldub [%g1 + %lo(global_irq_holder)], %g5 - cmp %g5, %g7 - bne ___irq_enter_out - mov NO_PROC_ID, %g2 - stb %g2, [%g1 + %lo(global_irq_holder)] - sethi %hi(global_irq_lock), %g5 - b ___irq_enter_out - stb %g0, [%g5 + %lo(global_irq_lock)] /* Weird calling conventions... %g7=flags, %g4=%prev_o7 * Very clever for the __global_sti case, the inline which diff -u --recursive --new-file v2.2.6/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.2.6/linux/arch/sparc/mm/init.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc/mm/init.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.63 1999/03/20 22:02:01 davem Exp $ +/* $Id: init.c,v 1.65 1999/04/09 16:28:03 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.2.6/linux/arch/sparc/mm/nosrmmu.c linux/arch/sparc/mm/nosrmmu.c --- v2.2.6/linux/arch/sparc/mm/nosrmmu.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/nosrmmu.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: nosrmmu.c,v 1.1 1998/03/09 14:04:15 jj Exp $ +/* $Id: nosrmmu.c,v 1.2 1999/03/30 10:17:39 jj Exp $ * nosrmmu.c: This file is a bunch of dummies for sun4 compiles, * so that it does not need srmmu and avoid ifdefs. * @@ -45,6 +45,16 @@ } __initfunc(void srmmu_end_memory(unsigned long memory_size, unsigned long *mem_end_p)) +{ + return 0; +} + +__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size) +{ + return 0; +} + +__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus) { return 0; } diff -u --recursive --new-file v2.2.6/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.2.6/linux/arch/sparc/mm/srmmu.c Mon Mar 29 11:09:11 1999 +++ linux/arch/sparc/mm/srmmu.c Wed Apr 28 10:58:10 1999 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.185 1999/03/24 11:42:35 davem Exp $ +/* $Id: srmmu.c,v 1.187 1999/04/28 17:00:45 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -1948,12 +1949,13 @@ /* Find the number of contexts on the srmmu. */ cpunode = prom_getchild(prom_root_node); num_contexts = 0; - while((cpunode = prom_getsibling(cpunode)) != 0) { + while(cpunode != 0) { prom_getstring(cpunode, "device_type", node_str, sizeof(node_str)); if(!strcmp(node_str, "cpu")) { num_contexts = prom_getintdefault(cpunode, "mmu-nctx", 0x8); break; } + cpunode = prom_getsibling(cpunode); } } @@ -2000,6 +2002,18 @@ start_mem = sparc_context_init(start_mem, num_contexts); start_mem = free_area_init(start_mem, end_mem); + +#ifdef CONFIG_BLK_DEV_INITRD + /* If initial ramdisk was specified with physical address, + translate it here, as the p2v translation in srmmu + is not straightforward. */ + if (initrd_start && initrd_start < KERNBASE) { + initrd_start = srmmu_p2v(initrd_start); + initrd_end = srmmu_p2v(initrd_end); + if (initrd_end <= initrd_start) + initrd_start = 0; + } +#endif return PAGE_ALIGN(start_mem); } diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.2.6/linux/arch/sparc64/config.in Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/config.in Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.65 1999/03/14 03:12:48 anton Exp $ +# $Id: config.in,v 1.66 1999/03/29 05:08:42 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -185,6 +185,7 @@ bool ' assume boards are SYMBIOS compatible' CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT fi fi + dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI fi endmenu diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.2.6/linux/arch/sparc64/defconfig Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/defconfig Thu Apr 22 19:24:51 1999 @@ -208,6 +208,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=10 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +CONFIG_SCSI_QLOGIC_ISP=y # # Fibre Channel support @@ -298,6 +299,8 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c --- v2.2.6/linux/arch/sparc64/kernel/cpu.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/cpu.c Wed Apr 28 08:47:39 1999 @@ -69,7 +69,7 @@ fprs = fprs_read (); fprs_write (FPRS_FEF); - __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" : "=r" (ver) : "r" (&fpu_vers)); + __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" : "=&r" (ver) : "r" (&fpu_vers)); fprs_write (fprs); manuf = ((ver >> 48)&0xffff); diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.2.6/linux/arch/sparc64/kernel/entry.S Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/entry.S Thu Apr 22 19:24:51 1999 @@ -1,10 +1,10 @@ -/* $Id: entry.S,v 1.101 1999/01/19 07:54:38 davem Exp $ +/* $Id: entry.S,v 1.102 1999/03/29 12:38:09 jj Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ #include @@ -163,6 +163,39 @@ wrpr %g3, %tstate wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits retry + + .globl do_fptrap + .align 32 +do_fptrap: + ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3 + stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr] + rd %fprs, %g1 + or %g3, %g1, %g3 + stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved] + rd %gsr, %g3 + stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_gsr] + mov SECONDARY_CONTEXT, %g3 + add %g6, AOFF_task_fpregs, %g2 + ldxa [%g3] ASI_DMMU, %g5 + stxa %g0, [%g3] ASI_DMMU + flush %g6 + membar #StoreStore | #LoadStore + andcc %g1, FPRS_DL, %g0 + be,pn %icc, 4f + mov 0x40, %g3 + stda %f0, [%g2] ASI_BLK_S + stda %f16, [%g2 + %g3] ASI_BLK_S + andcc %g1, FPRS_DU, %g0 + be,pn %icc, 5f +4: add %g2, 128, %g2 + stda %f32, [%g2] ASI_BLK_S + stda %f48, [%g2 + %g3] ASI_BLK_S +5: mov SECONDARY_CONTEXT, %g1 + membar #Sync + stxa %g5, [%g1] ASI_DMMU + flush %g6 + ba,pt %xcc, etrap + wr %g0, 0, %fprs /* The registers for cross calls will be: * diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.2.6/linux/arch/sparc64/kernel/head.S Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/head.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.59 1999/01/06 01:37:35 davem Exp $ +/* $Id: head.S,v 1.60 1999/04/12 08:08:21 davem Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -47,7 +47,7 @@ * HdrS version should be incremented. */ .global root_flags, ram_flags, root_dev - .global ramdisk_image, ramdisk_size + .global sparc_ramdisk_image, sparc_ramdisk_size .globl silo_args .ascii "HdrS" @@ -59,9 +59,9 @@ .half 0 ram_flags: .half 0 -ramdisk_image: +sparc_ramdisk_image: .word 0 -ramdisk_size: +sparc_ramdisk_size: .word 0 .xword reboot_command .xword bootstr_len diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.2.6/linux/arch/sparc64/kernel/irq.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/irq.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.75 1999/01/28 12:37:56 jj Exp $ +/* $Id: irq.c,v 1.76 1999/04/02 14:54:30 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -309,7 +309,7 @@ unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap) { struct ino_bucket *bucket; - unsigned short ino; + int ino; if(pil == 0) { if(iclr != NULL || imap != NULL) { diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.2.6/linux/arch/sparc64/kernel/psycho.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/psycho.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: psycho.c,v 1.79 1999/03/19 05:38:46 davem Exp $ +/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $ * psycho.c: Ultra/AX U2P PCI controller support. * * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) @@ -680,20 +680,23 @@ { unsigned int devfn, l, class; unsigned char hdr_type = 0; + int is_multi = 0; for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - pbm_read_config_byte(pbm, bus, devfn, - PCI_HEADER_TYPE, &hdr_type); - } else if (!(hdr_type & 0x80)) { + if (PCI_FUNC(devfn) != 0 && is_multi == 0) { /* not a multi-function device */ continue; } + pbm_read_config_byte(pbm, bus, devfn, + PCI_HEADER_TYPE, &hdr_type); + if (PCI_FUNC(devfn) == 0) + is_multi = hdr_type & 0x80; /* Check if there is anything here. */ pbm_read_config_dword(pbm, bus, devfn, PCI_VENDOR_ID, &l); - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; + if (l == 0xffffffff || l == 0x00000000 || + l == 0x0000ffff || l == 0xffff0000) { + is_multi = 0; continue; } @@ -1234,12 +1237,13 @@ } if (bsreg == PCI_ROM_ADDRESS) { pdev->rom_address = (unsigned long)__va(pci_addr); - pdev->rom_address |= 1; + pdev->rom_address &= ~1UL; + /* - * Enable access to the ROM. + * Disable access to the ROM. */ pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &rtmp); - pci_write_config_dword(pdev, PCI_ROM_ADDRESS, rtmp | 1); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, rtmp & ~1); } else pdev->base_address[brindex] = (unsigned long)__va(pci_addr); @@ -1408,7 +1412,7 @@ rtmp = new_base; pci_read_config_dword(pdev, breg, &base); - rtmp |= (base & ~PCI_ROM_ADDRESS_MASK); + rtmp &= ~(base & ~PCI_ROM_ADDRESS_MASK); pci_write_config_dword(pdev, breg, rtmp); /* Apply PBM ranges and update pci_dev. */ @@ -1431,8 +1435,7 @@ "PBM ranges\n"); } pdev->rom_address = (unsigned long)__va(pci_addr); - - pdev->rom_address |= (base & ~PCI_ROM_ADDRESS_MASK); + pdev->rom_address &= ~(base & ~PCI_ROM_ADDRESS_MASK); MEM_seen = 1; } rom_address_done: @@ -1588,6 +1591,36 @@ imap_off = imap_offset(imap_ser); break; + case 0x2c: + /* Onboard Timer 0 */ + imap_off = imap_offset(imap_tim0); + break; + + case 0x2d: + /* Onboard Timer 1 */ + imap_off = imap_offset(imap_tim1); + break; + + case 0x2e: + /* Psycho UE Interrupt */ + imap_off = imap_offset(imap_ue); + break; + + case 0x2f: + /* Psycho CE Interrupt */ + imap_off = imap_offset(imap_ce); + break; + + case 0x30: + /* Psycho PCI A Error Interrupt */ + imap_off = imap_offset(imap_a_err); + break; + + case 0x31: + /* Psycho PCI B Error Interrupt */ + imap_off = imap_offset(imap_b_err); + break; + case 0x32: /* Power Management */ imap_off = imap_offset(imap_pmgmt); @@ -1720,7 +1753,6 @@ int node) { unsigned int prom_irq, portid = pbm->parent->upa_portid; - unsigned char pci_irq_line = pdev->irq; int err; #ifdef FIXUP_IRQ_DEBUG @@ -1764,7 +1796,25 @@ unsigned int bus, slot, line; bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0; - line = (pci_irq_line) & 3; + + /* Use the given interrupt property value as the line if it + * is non-zero and legal. Legal encodings are INTA=1, INTB=2, + * INTC=3, INTD=4 as per PCI OBP binding spec version 2.1 -DaveM + */ + if(prom_irq > 0 && prom_irq < 5) { + line = ((prom_irq - 1) & 3); + } else { + unsigned char pci_irq_line; + + /* The generic PCI probing layer will read the + * interrupt line into pdev->irq if the interrupt + * pin is non-zero, so we have to explicitly fetch + * the pin here to be certain (the interrupt line is + * typically left at zero by OBP). + */ + pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line); + line = ((pci_irq_line - 1) & 3); + } /* Slot determination is only slightly complex. Handle * the easy case first. diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.2.6/linux/arch/sparc64/kernel/setup.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/setup.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.41 1999/01/04 20:12:25 davem Exp $ +/* $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -413,13 +413,12 @@ extern int prom_probe_memory(void); extern unsigned long start, end; extern void panic_setup(char *, int *); -extern unsigned long sun_serial_setup(unsigned long); extern unsigned short root_flags; extern unsigned short root_dev; extern unsigned short ram_flags; -extern unsigned int ramdisk_image; -extern unsigned int ramdisk_size; +extern unsigned int sparc_ramdisk_image; +extern unsigned int sparc_ramdisk_size; #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 @@ -509,13 +508,13 @@ rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif #ifdef CONFIG_BLK_DEV_INITRD - if (ramdisk_image) { + if (sparc_ramdisk_image) { unsigned long start = 0; - if (ramdisk_image >= (unsigned long)&end - 2 * PAGE_SIZE) - ramdisk_image -= KERNBASE; - initrd_start = ramdisk_image + phys_base + PAGE_OFFSET; - initrd_end = initrd_start + ramdisk_size; + if (sparc_ramdisk_image >= (unsigned long)&end - 2 * PAGE_SIZE) + sparc_ramdisk_image -= KERNBASE; + initrd_start = sparc_ramdisk_image + phys_base + PAGE_OFFSET; + initrd_end = initrd_start + sparc_ramdisk_size; if (initrd_end > *memory_end_p) { printk(KERN_CRIT "initrd extends beyond end of memory " "(0x%016lx > 0x%016lx)\ndisabling initrd\n", @@ -523,10 +522,10 @@ initrd_start = 0; } if (initrd_start) - start = ramdisk_image + KERNBASE; + start = sparc_ramdisk_image + KERNBASE; if (start >= *memory_start_p && start < *memory_start_p + 2 * PAGE_SIZE) { initrd_below_start_ok = 1; - *memory_start_p = PAGE_ALIGN (start + ramdisk_size); + *memory_start_p = PAGE_ALIGN (start + sparc_ramdisk_size); } } #endif @@ -586,7 +585,6 @@ serial_console = 2; break; } - *memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */ #else serial_console = 0; #endif diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.2.6/linux/arch/sparc64/kernel/smp.c Mon Mar 29 11:09:11 1999 +++ linux/arch/sparc64/kernel/smp.c Thu Apr 22 19:24:51 1999 @@ -380,37 +380,51 @@ * to the stack before we get here because all callers of us * are flush_tlb_*() routines, and these run after flush_cache_*() * which performs the flushw. + * + * The SMP TLB coherency scheme we use works as follows: + * + * 1) mm->cpu_vm_mask is a bit mask of which cpus an address + * space has (potentially) executed on, this is the heuristic + * we use to avoid doing cross calls. + * + * 2) TLB context numbers are shared globally across all processors + * in the system, this allows us to play several games to avoid + * cross calls. + * + * One invariant is that when a cpu switches to a process, and + * that processes tsk->mm->cpu_vm_mask does not have the current + * cpu's bit set, that tlb context is flushed locally. + * + * If the address space is non-shared (ie. mm->count == 1) we avoid + * cross calls when we want to flush the currently running process's + * tlb state. This is done by clearing all cpu bits except the current + * processor's in current->mm->cpu_vm_mask and performing the flush + * locally only. This will force any subsequent cpus which run this + * task to flush the context from the local tlb if the process migrates + * to another cpu (again). + * + * 3) For shared address spaces (threads) and swapping we bite the + * bullet for most cases and perform the cross call. + * + * The performance gain from "optimizing" away the cross call for threads is + * questionable (in theory the big win for threads is the massive sharing of + * address space state across processors). + * + * For the swapping case the locking is difficult to get right, we'd have to + * enforce strict ordered access to mm->cpu_vm_mask via a spinlock for example. + * Then again one could argue that when you are swapping, the cost of a cross + * call won't even show up on the performance radar. But in any case we do get + * rid of the cross-call when the task has a dead context or the task has only + * ever run on the local cpu. */ -static void smp_cross_call_avoidance(struct mm_struct *mm) -{ - u32 ctx; - - spin_lock(&scheduler_lock); - get_new_mmu_context(mm); - mm->cpu_vm_mask = (1UL << smp_processor_id()); - current->tss.ctx = ctx = mm->context & 0x3ff; - spitfire_set_secondary_context(ctx); - __asm__ __volatile__("flush %g6"); - spitfire_flush_dtlb_secondary_context(); - spitfire_flush_itlb_secondary_context(); - __asm__ __volatile__("flush %g6"); - if(!segment_eq(current->tss.current_ds,USER_DS)) { - /* Rarely happens. */ - current->tss.ctx = 0; - spitfire_set_secondary_context(0); - __asm__ __volatile__("flush %g6"); - } - spin_unlock(&scheduler_lock); -} - void smp_flush_tlb_mm(struct mm_struct *mm) { u32 ctx = mm->context & 0x3ff; if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask == (1UL << smp_processor_id())) - goto local_flush_and_out; - return smp_cross_call_avoidance(mm); + if(mm->cpu_vm_mask != (1UL << smp_processor_id())) + mm->cpu_vm_mask = (1UL << smp_processor_id()); + goto local_flush_and_out; } smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); @@ -426,9 +440,9 @@ start &= PAGE_MASK; end &= PAGE_MASK; if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask == (1UL << smp_processor_id())) - goto local_flush_and_out; - return smp_cross_call_avoidance(mm); + if(mm->cpu_vm_mask != (1UL << smp_processor_id())) + mm->cpu_vm_mask = (1UL << smp_processor_id()); + goto local_flush_and_out; } smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); @@ -442,22 +456,32 @@ page &= PAGE_MASK; if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask == (1UL << smp_processor_id())) - goto local_flush_and_out; - return smp_cross_call_avoidance(mm); - } -#if 0 /* XXX Disabled until further notice... */ - else if(atomic_read(&mm->count) == 1) { + if(mm->cpu_vm_mask != (1UL << smp_processor_id())) + mm->cpu_vm_mask = (1UL << smp_processor_id()); + goto local_flush_and_out; + } else { + spin_lock(&scheduler_lock); + /* Try to handle two special cases to avoid cross calls * in common scenerios where we are swapping process * pages out. */ - if((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) + if(((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) || + (mm->cpu_vm_mask == 0)) { + /* A dead context cannot ever become "alive" until + * a task switch is done to it. + */ + spin_unlock(&scheduler_lock); return; /* It's dead, nothing to do. */ - if(mm->cpu_vm_mask == (1UL << smp_processor_id())) - goto local_flush_and_out; + } + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) { + spin_unlock(&scheduler_lock); + __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); + return; /* Only local flush is necessary. */ + } + + spin_unlock(&scheduler_lock); } -#endif smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); local_flush_and_out: diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.2.6/linux/arch/sparc64/kernel/systbls.S Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/systbls.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.52 1999/03/20 22:02:05 davem Exp $ +/* $Id: systbls.S,v 1.53 1999/04/07 17:14:11 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -26,7 +26,7 @@ /*30*/ .word sys32_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice .word sys_nis_syscall, sys_sync, sys_kill, sys32_newstat, sys32_sendfile /*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall - .word sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid + .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys32_execve /*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize @@ -48,7 +48,7 @@ /*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit .word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall - .word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_umount + .word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents @@ -85,7 +85,7 @@ /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice .word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile /*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall - .word sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid + .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize @@ -107,7 +107,7 @@ /*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit .word sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall - .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount + .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents @@ -188,7 +188,7 @@ /*150*/ .word sys_getsockname, sunos_nosys, sunos_nosys .word sys_poll, sunos_nosys, sunos_nosys .word sunos_getdirentries, sys32_statfs, sys32_fstatfs - .word sys_umount, sunos_nosys, sunos_nosys + .word sys_oldumount, sunos_nosys, sunos_nosys .word sys_getdomainname, sys_setdomainname .word sunos_nosys, sys32_quotactl, sunos_nosys .word sunos_mount, sys_ustat, sunos_semsys diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.2.6/linux/arch/sparc64/kernel/traps.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/traps.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.57 1999/03/02 15:42:18 jj Exp $ +/* $Id: traps.c,v 1.58 1999/03/29 12:38:10 jj Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -406,8 +406,6 @@ void do_fpieee(struct pt_regs *regs) { #ifdef DEBUG_FPU - save_and_clear_fpu(); - printk("fpieee %016lx\n", current->tss.xfsr[0]); #endif do_fpe_common(regs); @@ -420,7 +418,6 @@ struct fpustate *f = FPUSTATE; int ret = 0; - save_and_clear_fpu(); switch ((current->tss.xfsr[0] & 0x1c000)) { case (2 << 14): /* unfinished_FPop */ case (3 << 14): /* unimplemented_FPop */ @@ -428,7 +425,7 @@ break; } if (ret) return; -#ifdef DEBUG_FPU +#ifdef DEBUG_FPU printk("fpother %016lx\n", current->tss.xfsr[0]); #endif do_fpe_common(regs); diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.2.6/linux/arch/sparc64/kernel/ttable.S Mon Oct 5 13:13:38 1998 +++ linux/arch/sparc64/kernel/ttable.S Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.27 1998/09/25 01:09:10 davem Exp $ +/* $Id: ttable.S,v 1.28 1999/03/29 12:38:10 jj Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -21,8 +21,8 @@ tl0_resv018: BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d) tl0_resv01e: BTRAP(0x1e) BTRAP(0x1f) tl0_fpdis: TRAP_NOSAVE(do_fpdis) -tl0_fpieee: TRAP(do_fpieee) -tl0_fpother: TRAP(do_fpother) +tl0_fpieee: TRAP_SAVEFPU(do_fpieee) +tl0_fpother: TRAP_SAVEFPU(do_fpother) tl0_tof: TRAP(do_tof) tl0_cwin: CLEAN_WINDOW tl0_div0: TRAP(do_div0) diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c --- v2.2.6/linux/arch/sparc64/kernel/unaligned.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/unaligned.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.14 1999/03/02 15:42:16 jj Exp $ +/* $Id: unaligned.c,v 1.15 1999/04/03 11:36:21 anton Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -374,7 +374,6 @@ enum direction dir = decode_direction(insn); int size = decode_access_size(insn); - lock_kernel(); if(!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n", regs->tpc); @@ -423,7 +422,6 @@ } advance(regs); } - unlock_kernel(); } static char popc_helper[] = { diff -u --recursive --new-file v2.2.6/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.2.6/linux/arch/sparc64/mm/init.c Mon Mar 29 11:09:11 1999 +++ linux/arch/sparc64/mm/init.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.125 1999/03/28 08:39:33 davem Exp $ +/* $Id: init.c,v 1.126 1999/04/09 16:16:41 jj Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -1127,6 +1127,7 @@ /* paging_init() sets up the page tables */ extern unsigned long free_area_init(unsigned long, unsigned long); +extern unsigned long sun_serial_setup(unsigned long); __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) @@ -1195,6 +1196,13 @@ * such that __pa() macros etc. work. */ mempool = PAGE_ALIGN(start_mem) + shift; + +#ifdef CONFIG_SUN_SERIAL + /* This does not logically belong here, but is the first place + we can initialize it at, so that we work in the PAGE_OFFSET+ + address space. */ + mempool = sun_serial_setup(mempool); +#endif /* Allocate 64M for dynamic DVMA mapping area. */ allocate_ptable_skeleton(DVMA_VADDR, DVMA_VADDR + 0x4000000); diff -u --recursive --new-file v2.2.6/linux/drivers/Makefile linux/drivers/Makefile --- v2.2.6/linux/drivers/Makefile Fri Nov 27 13:09:22 1998 +++ linux/drivers/Makefile Sat Apr 24 18:45:18 1999 @@ -10,7 +10,7 @@ SUB_DIRS := block char net misc sound MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \ - macintosh video dio zorro fc4 + macintosh video dio zorro fc4 usb ifdef CONFIG_DIO SUB_DIRS += dio @@ -42,6 +42,11 @@ ifdef CONFIG_PPC SUB_DIRS += macintosh MOD_SUB_DIRS += macintosh +endif + +ifeq ($(CONFIG_USB),y) +SUB_DIRS += usb +MOD_SUB_DIRS += usb endif # If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel, diff -u --recursive --new-file v2.2.6/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c --- v2.2.6/linux/drivers/acorn/char/keyb_ps2.c Tue Dec 22 14:16:54 1998 +++ linux/drivers/acorn/char/keyb_ps2.c Mon Apr 26 13:31:49 1999 @@ -221,11 +221,6 @@ }; #endif -int ps2kbd_pretranslate(unsigned char scancode) -{ - return 1; -} - int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *uf_p) { *uf_p = scancode & 0200; @@ -235,7 +230,7 @@ static void ps2kbd_key(unsigned int keycode, unsigned int up_flag) { - handle_scancode(keycode + (up_flag ? 0x80 : 0)); + handle_scancode(keycode, !up_flag); } static inline void ps2kbd_sendbyte(unsigned char val) diff -u --recursive --new-file v2.2.6/linux/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h --- v2.2.6/linux/drivers/block/ide-cd.h Tue Mar 23 14:35:47 1999 +++ linux/drivers/block/ide-cd.h Tue Apr 27 09:56:22 1999 @@ -334,13 +334,13 @@ #if defined(__BIG_ENDIAN_BITFIELD) __u8 reserved3 : 2; - /* Drive can fake writes */ - __u8 test_write : 1; - __u8 reserved3a : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; /* Drive can write DVD-RAM discs */ __u8 dvd_ram_write : 1; + /* Drive can write DVD-R discs */ + __u8 dvd_r_write : 1; + __u8 reserved3a : 1; + /* Drive can fake writes */ + __u8 test_write : 1; /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ __u8 cd_rw_write : 1; /* reserved in 1.2 */ /* Drive supports write to CD-R discs (orange book, part II) */ @@ -350,13 +350,13 @@ __u8 cd_r_write : 1; /* reserved in 1.2 */ /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - __u8 reserved3a : 1; /* Drive can fake writes */ __u8 test_write : 1; + __u8 reserved3a : 1; + /* Drive can write DVD-R discs */ + __u8 dvd_r_write : 1; + /* Drive can write DVD-RAM discs */ + __u8 dvd_ram_write : 1; __u8 reserved3 : 2; #else #error "Please fix " diff -u --recursive --new-file v2.2.6/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.2.6/linux/drivers/block/rd.c Mon Mar 29 11:09:11 1999 +++ linux/drivers/block/rd.c Tue Apr 27 09:24:34 1999 @@ -295,6 +295,8 @@ #ifdef MODULE +MODULE_PARM (rd_size, "1i"); + int init_module(void) { int error = rd_init(); diff -u --recursive --new-file v2.2.6/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c --- v2.2.6/linux/drivers/cdrom/optcd.c Wed Aug 26 11:37:36 1998 +++ linux/drivers/cdrom/optcd.c Sat Apr 24 17:49:37 1999 @@ -100,6 +100,10 @@ #else #define DEBUG(x) #endif + +static int blksize = 2048; +static int hsecsize = 2048; + /* Drive hardware/firmware characteristics Identifiers in accordance with Optics Storage documentation */ @@ -2061,6 +2065,8 @@ return -EIO; } + hardsect_size[MAJOR_NR] = &hsecsize; + blksize_size[MAJOR_NR] = &blksize; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 4; request_region(optcd_port, 4, "optcd"); diff -u --recursive --new-file v2.2.6/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.2.6/linux/drivers/char/Makefile Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/Makefile Mon Apr 26 11:08:17 1999 @@ -42,14 +42,15 @@ ifndef CONFIG_SUN_KEYBOARD ifdef CONFIG_VT -L_OBJS += keyboard.o +LX_OBJS += keyboard.o endif ifneq ($(ARCH),m68k) L_OBJS += pc_keyb.o defkeymap.o endif else ifdef CONFIG_PCI -L_OBJS += defkeymap.o keyboard.o +L_OBJS += defkeymap.o +LX_OBJS += keyboard.o endif endif diff -u --recursive --new-file v2.2.6/linux/drivers/char/amikeyb.c linux/drivers/char/amikeyb.c --- v2.2.6/linux/drivers/char/amikeyb.c Mon Aug 3 12:45:45 1998 +++ linux/drivers/char/amikeyb.c Mon Apr 26 13:25:54 1999 @@ -188,7 +188,7 @@ amikeyb_rep_timer.expires = jiffies + key_repeat_rate; amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; add_timer(&amikeyb_rep_timer); - handle_scancode(rep_scancode); + handle_scancode(rep_scancode, 1); restore_flags(flags); } @@ -243,8 +243,8 @@ if (keycode == AMIKEY_CAPS) { /* if the key is CAPS, fake a press/release. */ - handle_scancode(AMIKEY_CAPS); - handle_scancode(BREAK_MASK | AMIKEY_CAPS); + handle_scancode(AMIKEY_CAPS, 1); + handle_scancode(AMIKEY_CAPS, 0); } else if (keycode < 0x78) { /* handle repeat */ if (break_flag) { @@ -257,7 +257,7 @@ amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; add_timer(&amikeyb_rep_timer); } - handle_scancode(scancode); + handle_scancode(scancode, !break_flag); } else switch (keycode) { case 0x78: diff -u --recursive --new-file v2.2.6/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.2.6/linux/drivers/char/bttv.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/bttv.c Sat Apr 24 17:49:37 1999 @@ -2853,6 +2853,16 @@ } #endif +static void init_tea6300(struct i2c_bus *bus) +{ + I2CWrite(bus, I2C_TEA6300, TEA6300_VL, 0x35, 1); /* volume left 0dB */ + I2CWrite(bus, I2C_TEA6300, TEA6300_VR, 0x35, 1); /* volume right 0dB */ + I2CWrite(bus, I2C_TEA6300, TEA6300_BA, 0x07, 1); /* bass 0dB */ + I2CWrite(bus, I2C_TEA6300, TEA6300_TR, 0x07, 1); /* treble 0dB */ + I2CWrite(bus, I2C_TEA6300, TEA6300_FA, 0x0f, 1); /* fader off */ + I2CWrite(bus, I2C_TEA6300, TEA6300_SW, 0x01, 1); /* mute off input A */ +} + static void init_tda8425(struct i2c_bus *bus) { I2CWrite(bus, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */ @@ -2978,6 +2988,14 @@ break; } + if (I2CRead(&(btv->i2c), I2C_TEA6300) >=0) + { + printk(KERN_INFO "bttv%d: fader chip: TEA6300\n",btv->nr); + btv->audio_chip = TEA6300; + init_tea6300(&(btv->i2c)); + } else + printk(KERN_INFO "bttv%d: NO fader chip: TEA6300\n",btv->nr); + printk(KERN_INFO "bttv%d: model: ",btv->nr); sprintf(btv->video_dev.name,"BT%d",btv->id); diff -u --recursive --new-file v2.2.6/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.2.6/linux/drivers/char/bttv.h Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/bttv.h Sat Apr 24 17:49:37 1999 @@ -114,6 +114,7 @@ int type; /* card type */ int audio; /* audio mode */ int audio_chip; + int fader_chip; int radio; u32 *risc_jmp; @@ -222,6 +223,7 @@ #define TDA9850 0x01 #define TDA8425 0x02 #define TDA9840 0x03 +#define TEA6300 0x04 #define I2C_TSA5522 0xc2 #define I2C_TDA9840 0x84 @@ -230,6 +232,7 @@ #define I2C_HAUPEE 0xa0 #define I2C_STBEE 0xae #define I2C_VHX 0xc0 +#define I2C_TEA6300 0x80 #define TDA9840_SW 0x00 #define TDA9840_LVADJ 0x02 @@ -249,6 +252,12 @@ #define TDA8425_BA 0x02 #define TDA8425_TR 0x03 #define TDA8425_S1 0x08 - + +#define TEA6300_VL 0x00 /* volume control left */ +#define TEA6300_VR 0x01 /* volume control right */ +#define TEA6300_BA 0x02 /* bass control */ +#define TEA6300_TR 0x03 /* treble control */ +#define TEA6300_FA 0x04 /* fader control */ +#define TEA6300_SW 0x05 /* mute and source switch */ #endif diff -u --recursive --new-file v2.2.6/linux/drivers/char/dn_keyb.c linux/drivers/char/dn_keyb.c --- v2.2.6/linux/drivers/char/dn_keyb.c Wed Aug 26 11:37:36 1998 +++ linux/drivers/char/dn_keyb.c Mon Apr 26 13:28:07 1999 @@ -414,9 +414,9 @@ } else if((scancode & (~BREAK_FLAG)) == DNKEY_CAPS) { /* printk("handle_scancode: %02x\n",DNKEY_CAPS); */ - handle_scancode(DNKEY_CAPS); + handle_scancode(DNKEY_CAPS, 1); /* printk("handle_scancode: %02x\n",BREAK_FLAG | DNKEY_CAPS); */ - handle_scancode(BREAK_FLAG | DNKEY_CAPS); + handle_scancode(DNKEY_CAPS, 0); } else if( (scancode == DNKEY_REPEAT) && (prev_scancode < 0x7e) && !(prev_scancode==DNKEY_CTRL || prev_scancode==DNKEY_LSHIFT || @@ -424,13 +424,13 @@ prev_scancode==DNKEY_LALT || prev_scancode==DNKEY_RALT)) { if(jiffies-lastkeypress > DNKEY_REPEAT_DELAY) { /* printk("handle_scancode: %02x\n",prev_scancode); */ - handle_scancode(prev_scancode); + handle_scancode(prev_scancode, 1); } lastscancode=prev_scancode; } else { /* printk("handle_scancode: %02x\n",scancode); */ - handle_scancode(scancode); + handle_scancode(scancode & ~BREAK_FLAG, !(scancode & BREAK_FLAG)); lastkeypress=jiffies; } } diff -u --recursive --new-file v2.2.6/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.2.6/linux/drivers/char/keyboard.c Fri Jan 8 22:36:05 1999 +++ linux/drivers/char/keyboard.c Mon Apr 26 13:21:42 1999 @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -59,6 +60,8 @@ #define KBD_DEFLOCK 0 #endif +EXPORT_SYMBOL(handle_scancode); + extern void ctrl_alt_del(void); struct wait_queue * keypress_wait = NULL; @@ -190,15 +193,15 @@ return kbd_getkeycode(scancode); } -void handle_scancode(unsigned char scancode) +void handle_scancode(unsigned char scancode, int down) { unsigned char keycode; - char up_flag; /* 0 or 0200 */ + char up_flag = down ? 0 : 0200; char raw_mode; do_poke_blanked_console = 1; mark_bh(CONSOLE_BH); - add_keyboard_randomness(scancode); + add_keyboard_randomness(scancode | up_flag); tty = ttytab? ttytab[fg_console]: NULL; if (tty && (!tty->driver_data)) { @@ -213,20 +216,15 @@ } kbd = kbd_table + fg_console; if ((raw_mode = (kbd->kbdmode == VC_RAW))) { - put_queue(scancode); + put_queue(scancode | up_flag); /* we do not return yet, because we want to maintain the key_down array, so that we have the correct values when finishing RAW mode or when changing VT's */ - } + } - if (!kbd_pretranslate(scancode, raw_mode)) - return; - /* + /* * Convert scancode to keycode - */ - up_flag = (scancode & 0200); - scancode &= 0x7f; - + */ if (!kbd_translate(scancode, &keycode, raw_mode)) return; @@ -239,10 +237,10 @@ if (up_flag) { rep = 0; - if(!test_and_clear_bit(keycode, key_down)) + if(!test_and_clear_bit(keycode, key_down)) up_flag = kbd_unexpected_up(keycode); } else - rep = test_and_set_bit(keycode, key_down); + rep = test_and_set_bit(keycode, key_down); #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ if (keycode == SYSRQ_KEY) { @@ -257,11 +255,11 @@ if (kbd->kbdmode == VC_MEDIUMRAW) { /* soon keycodes will require more than one byte */ - put_queue(keycode + up_flag); + put_queue(keycode + up_flag); raw_mode = 1; /* Most key classes will be ignored */ - } + } - /* + /* * Small change in philosophy: earlier we defined repetition by * rep = keycode == prev_keycode; * prev_keycode = keycode; @@ -270,9 +268,9 @@ */ /* - * Repeat a key only if the input buffers are empty or the - * characters get echoed locally. This makes key repeat usable - * with slow applications and under heavy loads. + * Repeat a key only if the input buffers are empty or the + * characters get echoed locally. This makes key repeat usable + * with slow applications and under heavy loads. */ if (!rep || (vc_kbd_mode(kbd,VC_REPEAT) && tty && diff -u --recursive --new-file v2.2.6/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.2.6/linux/drivers/char/mem.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/mem.c Mon Apr 26 12:55:29 1999 @@ -51,6 +51,12 @@ #if defined(CONFIG_PPC) || defined(CONFIG_MAC) extern void adbdev_init(void); #endif +#ifdef CONFIG_USB_UHCI +int uhci_init(void); +#endif +#ifdef CONFIG_USB_OHCI +int ohci_init(void); +#endif static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, const char * buf, size_t count, loff_t *ppos) @@ -599,6 +605,12 @@ if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); rand_initialize(); +#ifdef CONFIG_USB_UHCI + uhci_init(); +#endif +#ifdef CONFIG_USB_OHCI + ohci_init(); +#endif #if defined (CONFIG_FB) fbmem_init(); #endif diff -u --recursive --new-file v2.2.6/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.2.6/linux/drivers/char/n_tty.c Tue Jan 19 11:32:51 1999 +++ linux/drivers/char/n_tty.c Sat Apr 24 17:49:37 1999 @@ -922,8 +922,14 @@ } } - if (down_interruptible(&tty->atomic_read)) - return -ERESTARTSYS; + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&tty->atomic_read)) + return -EAGAIN; + } + else { + if (down_interruptible(&tty->atomic_read)) + return -ERESTARTSYS; + } add_wait_queue(&tty->read_wait, &wait); set_bit(TTY_DONT_FLIP, &tty->flags); diff -u --recursive --new-file v2.2.6/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.2.6/linux/drivers/char/pc_keyb.c Tue Feb 23 15:21:33 1999 +++ linux/drivers/char/pc_keyb.c Mon Apr 26 13:43:01 1999 @@ -240,8 +240,6 @@ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ }; -static unsigned int prev_scancode = 0; /* remember E0, E1 */ - int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) { if (scancode < SC_LIM || scancode > 255 || keycode > 127) @@ -284,41 +282,28 @@ scancode); #endif } - if (scancode == 0) { -#ifdef KBD_REPORT_ERR - printk(KERN_INFO "Keyboard buffer overflow\n"); -#endif - prev_scancode = 0; - return 0; - } return 1; } -int pckbd_pretranslate(unsigned char scancode, char raw_mode) +int pckbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) { - if (scancode == 0xff) { - /* in scancode mode 1, my ESC key generates 0xff */ - /* the calculator keys on a FOCUS 9000 generate 0xff */ -#ifndef KBD_IS_FOCUS_9000 -#ifdef KBD_REPORT_ERR - if (!raw_mode) - printk(KERN_DEBUG "Keyboard error\n"); -#endif -#endif - prev_scancode = 0; - return 0; - } + static int prev_scancode = 0; + /* special prefix scancodes.. */ if (scancode == 0xe0 || scancode == 0xe1) { prev_scancode = scancode; return 0; - } - return 1; -} + } + + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; -int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) -{ if (prev_scancode) { /* * usually it will be 0xe0, but a Pause key generates @@ -452,7 +437,7 @@ handle_mouse_event(scancode); } else { if (do_acknowledge(scancode)) - handle_scancode(scancode); + handle_scancode(scancode, !(scancode & 0x80)); mark_bh(KEYBOARD_BH); } diff -u --recursive --new-file v2.2.6/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c --- v2.2.6/linux/drivers/char/radio-sf16fmi.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/radio-sf16fmi.c Sat Apr 24 17:49:37 1999 @@ -4,6 +4,7 @@ * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz * * Fitted to new interface by Alan Cox + * Made working and cleaned up functions * * Notes on the hardware * @@ -74,9 +75,10 @@ outb(0x08, port); } -static inline int fmi_setfreq(struct fmi_device *dev, unsigned long freq) +static inline int fmi_setfreq(struct fmi_device *dev) { int myport = dev->port; + unsigned long freq = dev->curfreq; int i; outbits(16, RSF16_ENCODE(freq), myport); @@ -158,7 +160,6 @@ v.flags=fmi->flags; v.mode=VIDEO_MODE_AUTO; v.signal = fmi_getsigstr(fmi); - strcpy(v.name, "FM"); if(copy_to_user(arg,&v, sizeof(v))) return -EFAULT; return 0; @@ -192,8 +193,10 @@ tmp *= 1000; if ( tmpRSF16_MAXFREQ ) return -EINVAL; - fmi->curfreq = tmp; - fmi_setfreq(fmi, fmi->curfreq); + /*rounding in steps of 800 to match th freq + that will be used */ + fmi->curfreq = (tmp/800)*800; + fmi_setfreq(fmi); return 0; } case VIDIOCGAUDIO: @@ -205,7 +208,7 @@ v.treble=0; v.flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); strcpy(v.name, "Radio"); - v.mode=VIDEO_SOUND_MONO; + v.mode=VIDEO_SOUND_STEREO; v.balance=0; v.step=0; /* No volume, just (un)mute */ if(copy_to_user(arg,&v, sizeof(v))) diff -u --recursive --new-file v2.2.6/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c --- v2.2.6/linux/drivers/char/radio-typhoon.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/radio-typhoon.c Sat Apr 24 17:49:37 1999 @@ -196,7 +196,7 @@ v.flags = VIDEO_TUNER_LOW; v.mode = VIDEO_MODE_AUTO; v.signal = 0xFFFF; /* We can't get the signal strength */ - strcpy(v.tuner, "FM"); + strcpy(v.name, "FM"); if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; diff -u --recursive --new-file v2.2.6/linux/drivers/char/softdog.c linux/drivers/char/softdog.c --- v2.2.6/linux/drivers/char/softdog.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/softdog.c Sat Apr 24 17:49:37 1999 @@ -132,7 +132,6 @@ static int softdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int i; static struct watchdog_info ident= { 0, diff -u --recursive --new-file v2.2.6/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.2.6/linux/drivers/macintosh/mac_keyb.c Tue Mar 23 14:35:47 1999 +++ linux/drivers/macintosh/mac_keyb.c Mon Apr 26 13:31:31 1999 @@ -194,7 +194,7 @@ extern struct kbd_struct kbd_table[]; extern struct wait_queue * keypress_wait; -extern void handle_scancode(unsigned char); +extern void handle_scancode(unsigned char, int); static struct adb_ids keyboard_ids; static struct adb_ids mouse_ids; @@ -234,11 +234,6 @@ return -EINVAL; } -int mackbd_pretranslate(unsigned char scancode, char raw_mode) -{ - return 1; -} - int mackbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) { @@ -338,8 +333,8 @@ switch (keycode) { /*case 0xb9:*/ case 0x39: - handle_scancode(0x39); - handle_scancode(0xb9); + handle_scancode(0x39, 1); + handle_scancode(0x39, 0); mark_bh(KEYBOARD_BH); return; case 0x47: @@ -349,7 +344,7 @@ } } - handle_scancode(keycode + up_flag); + handle_scancode(keycode, !up_flag); } static void diff -u --recursive --new-file v2.2.6/linux/drivers/net/3c523.c linux/drivers/net/3c523.c --- v2.2.6/linux/drivers/net/3c523.c Tue Jan 19 11:32:51 1999 +++ linux/drivers/net/3c523.c Sat Apr 24 17:49:37 1999 @@ -62,8 +62,8 @@ search the MCA slots until it finds a 3c523 with the specified parameters. - This driver should support multiple ethernet cards, but I can't test - that. If someone would I'd greatly appreciate it. + This driver does support multiple ethernet cards when used as a module + (up to MAX_3C523_CARDS, the default being 4) This has been tested with both BNC and TP versions, internal and external transceivers. Haven't tested with the 64K version (that I @@ -76,7 +76,12 @@ update to 1.3.59, incorporated multicast diffs from ni52.c Feb 15th, 1996 added shared irq support - + Apr 1999 + added support for multiple cards when used as a module + added option to disable multicast as is causes problems + Ganesh Sittampalam + Stuart Adamson + $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ */ @@ -107,6 +112,7 @@ /*************************************************************************/ #define DEBUG /* debug on */ #define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */ +#undef ELMC_MULTICAST /* Disable multicast support as it is somewhat seriously broken at the moment */ #define make32(ptr16) (p->memtop + (short) (ptr16) ) #define make24(ptr32) ((char *) (ptr32) - p->base) @@ -180,7 +186,9 @@ static int elmc_close(struct device *dev); static int elmc_send_packet(struct sk_buff *, struct device *); static struct net_device_stats *elmc_get_stats(struct device *dev); +#ifdef ELMC_MULTICAST static void set_multicast_list(struct device *dev); +#endif /* helper-functions */ static int init586(struct device *dev); @@ -432,21 +440,19 @@ while (slot != -1) { status = mca_read_stored_pos(slot, 2); + dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]; + dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]; + /* If we're trying to match a specified irq or IO address, we'll reject a match unless it's what we're looking for. + Also reject it if the card is already in use. */ - if (base_addr || irq) { - /* we're looking for a card at a particular place */ - if (irq && irq != irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]) { - slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); - continue; - } - if (base_addr && base_addr != csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]) { - slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); - continue; - } + if((irq && irq != dev->irq) || (base_addr && base_addr != dev->base_addr) + || check_region(dev->base_addr,ELMC_IO_EXTENT)) { + slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); + continue; } /* found what we're looking for... */ break; @@ -476,9 +482,6 @@ /* revision is stored in the first 4 bits of the revision register */ revision = inb(dev->base_addr + ELMC_REVISION) & 0xf; - /* figure out our irq */ - dev->irq = irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]; - /* according to docs, we read the interrupt and write it back to the IRQ select register, since the POST might not configure the IRQ properly. */ @@ -497,9 +500,6 @@ break; } - /* Our IO address? */ - dev->base_addr = csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]; - request_region(dev->base_addr, ELMC_IO_EXTENT, "3c523"); dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL); @@ -565,7 +565,11 @@ dev->stop = &elmc_close; dev->get_stats = &elmc_get_stats; dev->hard_start_xmit = &elmc_send_packet; +#ifdef ELMC_MULTICAST dev->set_multicast_list = &set_multicast_list; +#else + dev->set_multicast_list = NULL; +#endif ether_setup(dev); @@ -577,6 +581,10 @@ That gets done in elmc_open(). I'm not sure that's such a good idea, but it works, so I'll go with it. */ +#ifndef ELMC_MULTICAST + dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ +#endif + return 0; } @@ -1210,6 +1218,7 @@ * Set MC list .. */ +#ifdef ELMC_MULTICAST static void set_multicast_list(struct device *dev) { if (!dev->start) { @@ -1222,60 +1231,85 @@ startrecv586(dev); dev->start = 1; } +#endif /*************************************************************************/ #ifdef MODULE -static char devicename[9] = {0,}; +/* Increase if needed ;) */ +#define MAX_3C523_CARDS 4 +/* I'm not sure where this magic 9 comes from */ +#define NAMELEN 9 -static struct device dev_elmc = -{ - devicename /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe +static char devicenames[NAMELEN * MAX_3C523_CARDS] = {0,}; + +static struct device dev_elmc[MAX_3C523_CARDS] = +{ + { + NULL /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL + }, }; -static int irq = 0; -static int io = 0; -MODULE_PARM(irq, "i"); -MODULE_PARM(io, "i"); +static int irq[MAX_3C523_CARDS] = {0,}; +static int io[MAX_3C523_CARDS] = {0,}; +MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); +MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); int init_module(void) { - struct device *dev = &dev_elmc; + int this_dev,found = 0; - dev->base_addr = io; - dev->irq = irq; - if (register_netdev(dev) != 0) { - return -EIO; - } - return 0; + /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */ + for(this_dev=0; this_devname=devicenames+(NAMELEN*this_dev); + dev->irq=irq[this_dev]; + dev->base_addr=io[this_dev]; + dev->init=elmc_probe; + if(register_netdev(dev)!=0) { + if(io[this_dev]==0) break; + printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); + } else found++; + } + + if(found==0) { + if(io[0]==0) printk(KERN_NOTICE "3c523.c: No 3c523 cards found\n"); + return -ENXIO; + } else return 0; } void cleanup_module(void) { - struct device *dev = &dev_elmc; + int this_dev; + for(this_dev=0; this_devirq != 0) { - /* this should be done by close, but if we failed to - initialize properly something may have gotten hosed. */ - free_irq(dev->irq, dev); - dev->irq = 0; - } - if (dev->base_addr != 0) { - release_region(dev->base_addr, ELMC_IO_EXTENT); - dev->base_addr = 0; - } - irq = 0; - io = 0; - unregister_netdev(dev); + struct device *dev = &dev_elmc[this_dev]; + if(dev->priv) { + /* shutdown interrupts on the card */ + elmc_id_reset586(); + if (dev->irq != 0) { + /* this should be done by close, but if we failed to + initialize properly something may have gotten hosed. */ + free_irq(dev->irq, dev); + dev->irq = 0; + } + if (dev->base_addr != 0) { + release_region(dev->base_addr, ELMC_IO_EXTENT); + dev->base_addr = 0; + } + irq[this_dev] = 0; + io[this_dev] = 0; + unregister_netdev(dev); - mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, + mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, NULL, NULL); - kfree_s(dev->priv, sizeof(struct priv)); - dev->priv = NULL; + kfree_s(dev->priv, sizeof(struct priv)); + dev->priv = NULL; + } + } } #endif /* MODULE */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c --- v2.2.6/linux/drivers/net/ibmtr.c Tue Mar 23 14:35:47 1999 +++ linux/drivers/net/ibmtr.c Sat Apr 24 17:49:37 1999 @@ -70,6 +70,12 @@ * Changes by Joel Sloan (jjs@c-me.com) : * + disable verbose debug messages by default - to enable verbose * debugging, edit the IBMTR_DEBUG_MESSAGES define below + * + * Changes by Mike Phillips : + * + Added extra #ifdef's to work with new PCMCIA Token Ring Code. + * The PCMCIA code now just sets up the card so it can be recognized + * by ibmtr_probe. Also checks allocated memory vs. on-board memory + * for correct figure to use. * * Changes by Tim Hockin (thockin@isunix.it.ilstu.edu) : * + added spinlocks for SMP sanity (10 March 1999) @@ -94,6 +100,7 @@ #undef NO_AUTODETECT #undef ENABLE_PAGING + #define FALSE 0 #define TRUE (!FALSE) @@ -191,6 +198,9 @@ int ibmtr_probe(struct device *dev); static int ibmtr_probe1(struct device *dev, int ioaddr); static unsigned char get_sram_size(struct tok_info *adapt_info); +#ifdef PCMCIA +extern unsigned char pcmcia_reality_check(unsigned char gss); +#endif static int tok_init_card(struct device *dev); void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int trdev_init(struct device *dev); @@ -256,8 +266,10 @@ if (ibmtr_probe1(dev, base_addr)) { #ifndef MODULE +#ifndef PCMCIA tr_freedev(dev); #endif +#endif return -ENODEV; } else return 0; @@ -272,8 +284,10 @@ continue; if (ibmtr_probe1(dev, ioaddr)) { #ifndef MODULE +#ifndef PCMCIA tr_freedev(dev); #endif +#endif } else return 0; } @@ -291,8 +305,10 @@ unsigned long timeout; #ifndef MODULE +#ifndef PCMCIA dev = init_trdev(dev,0); #endif +#endif /* Query the adapter PIO base port which will return * indication of where MMIO was placed. We also have a @@ -300,7 +316,7 @@ */ segment = inb(PIOaddr); - + /* * Out of range values so we'll assume non-existent IO device */ @@ -373,12 +389,19 @@ } /* Now, allocate some of the pl0 buffers for this driver.. */ + + /* If called from PCMCIA, ti is already set up, so no need to + waste the memory, just use the existing structure */ + +#ifndef PCMCIA ti = (struct tok_info *)kmalloc(sizeof(struct tok_info), GFP_KERNEL); if (ti == NULL) return -ENOMEM; memset(ti, 0, sizeof(struct tok_info)); - +#else + ti = dev->priv ; +#endif ti->mmio= t_mmio; ti->readlog_pending = 0; @@ -388,6 +411,10 @@ should fit with out future hope of multiple adapter support as well /dwm */ + /* if PCMCIA, then the card is recognized as TR_ISAPNP + * and there is no need to set up the interrupt, it is already done. */ + +#ifndef PCMCIA switch (cardpresent) { case TR_ISA: @@ -428,7 +455,6 @@ irq=10; if (intr==3) irq=11; - timeout = jiffies + TR_SPIN_INTERVAL; while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)) if (time_after(jiffies, timeout)) { @@ -436,11 +462,13 @@ kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; } + ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12); ti->global_int_enable=PIOaddr+ADAPTINTREL; ti->adapter_int_enable=PIOaddr+ADAPTINTREL; break; } +#endif if (ibmtr_debug_trace & TRC_INIT) { /* just report int */ DPRINTK("irq=%d",irq); @@ -483,8 +511,11 @@ ti->token_release = readb(ti->mmio + AIPEARLYTOKEN); /* How much shared RAM is on adapter ? */ +#ifdef PCMCIA + ti->avail_shared_ram = pcmcia_reality_check(get_sram_size(ti)); +#else ti->avail_shared_ram = get_sram_size(ti); - +#endif /* We need to set or do a bunch of work here based on previous results.. */ /* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */ ti->shared_ram_paging = readb(ti->mmio + AIPSHRAMPAGE); @@ -593,7 +624,6 @@ } #endif } - /* finish figuring the shared RAM address */ if (cardpresent==TR_ISA) { static __u32 ram_bndry_mask[]={0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000}; @@ -619,15 +649,20 @@ DPRINTK("Using %dK shared RAM\n",ti->mapped_ram_size/2); #endif + /* The PCMCIA has already got the interrupt line and the io port, + so no chance of anybody else getting it - MLP */ + +#ifndef PCMCIA if (request_irq (dev->irq = irq, &tok_interrupt,0,"ibmtr", dev) != 0) { DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",irq); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; } + + /*?? Now, allocate some of the PIO PORTs for this driver.. */ + request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range as busy */ +#endif - /*?? Now, allocate some of the PIO PORTs for this driver.. */ - request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range - as busy */ #if !TR_NEWFORMAT DPRINTK("%s",version); /* As we have passed card identification, let the world know we're here! */ @@ -717,7 +752,6 @@ unsigned char avail_sram_code; static unsigned char size_code[]={ 0,16,32,64,127,128 }; - /* Adapter gives 'F' -- use RRR bits 3,2 'E' -- 8kb 'D' -- 16kb @@ -747,8 +781,10 @@ dev->change_mtu = ibmtr_change_mtu; #ifndef MODULE +#ifndef PCMCIA tr_setup(dev); #endif +#endif return 0; } @@ -842,7 +878,7 @@ DPRINTK("PCMCIA card removed.\n"); spin_unlock(&(ti->lock)); dev->interrupt = 0; - return; + return; } /* Check ISRP EVEN too. */ @@ -1186,7 +1222,6 @@ __u32 encoded_addr; __u32 hw_encoded_addr; struct tok_info *ti; - ti=(struct tok_info *) dev->priv; ti->do_tok_int=NOT_FIRST; diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c --- v2.2.6/linux/drivers/net/irda/actisys.c Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/irda/actisys.c Sat Apr 24 17:49:37 1999 @@ -7,7 +7,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Tue Feb 9 15:38:16 1999 + * Modified at: Mon Apr 12 11:56:35 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -234,8 +234,8 @@ /* Remove support for 38400 if this is not a 220L+ dongle */ if ( idev->io.dongle_id == ACTISYS_DONGLE) qos->baud_rate.bits &= ~IR_38400; - - qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */ + + qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ } #ifdef MODULE diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c --- v2.2.6/linux/drivers/net/irda/esi.c Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/irda/esi.c Sat Apr 24 17:49:37 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Thomas Davis, * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Tue Feb 9 15:36:47 1999 + * Modified at: Mon Apr 12 11:55:30 1999 * Modified by: Dag Brattli * Sources: esi.c * @@ -56,9 +56,9 @@ esi_qos_init, }; -__initfunc(void esi_init(void)) +__initfunc(int esi_init(void)) { - irtty_register_dongle( &dongle); + return irtty_register_dongle(&dongle); } void esi_cleanup(void) @@ -132,7 +132,7 @@ } /* Change speed of serial driver */ tty->termios->c_cflag = cflag; - tty->driver.set_termios( tty, &old_termios); + tty->driver.set_termios(tty, &old_termios); irtty_set_dtr_rts(tty, dtr, rts); } @@ -151,6 +151,7 @@ static void esi_qos_init( struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; + qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ } #ifdef MODULE @@ -163,8 +164,7 @@ */ int init_module(void) { - esi_init(); - return(0); + return esi_init(); } /* diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c --- v2.2.6/linux/drivers/net/irda/girbil.c Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/irda/girbil.c Sat Apr 24 17:49:37 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Tue Feb 9 15:36:36 1999 + * Modified at: Sat Apr 10 19:53:12 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -195,7 +195,7 @@ { struct irtty_cb *self; struct tty_struct *tty; - __u8 control = GIRBIL_TXEN | GIRBIL_RXEN /* | GIRBIL_ECAN */; + __u8 control = GIRBIL_TXEN | GIRBIL_RXEN; ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- v2.2.6/linux/drivers/net/irda/irport.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/irport.c Sat Apr 24 17:49:37 1999 @@ -1,7 +1,7 @@ /********************************************************************* * * Filename: irport.c - * Version: 0.8 + * Version: 0.9 * Description: Serial driver for IrDA. * Status: Experimental. * Author: Dag Brattli @@ -9,7 +9,6 @@ * Modified at: Sat May 23 23:15:20 1998 * Modified by: Dag Brattli * Sources: serial.c by Linus Torvalds - * serial_serial.c by Aage Kvalnes * * Copyright (c) 1997,1998 Dag Brattli * All Rights Reserved. @@ -25,10 +24,10 @@ * * NOTICE: * - * This driver is ment to be a small serial driver to be used for - * IR-chipsets that has a UART (16550) compatibility mode. If your - * chipset is is UART only, you should probably use IrTTY instead since - * the Linux serial driver is probably more robust and optimized. + * This driver is ment to be a small half duplex serial driver to be + * used for IR-chipsets that has a UART (16550) compatibility mode. If + * your chipset is is UART only, you should probably use IrTTY instead + * since the Linux serial driver is probably more robust and optimized. * * The functions in this file may be used by FIR drivers, but this * driver knows nothing about FIR drivers so don't ever insert such @@ -64,7 +63,6 @@ #include #define IO_EXTENT 8 -#define CONFIG_HALF_DUPLEX /* static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 }; */ /* static unsigned int irq[] = { 11, 0, 0, 0 }; */ @@ -114,7 +112,7 @@ * Start IO port * */ -int irport_open( int iobase) +int irport_open(int iobase) { DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); @@ -134,7 +132,7 @@ * Stop IO port * */ -void irport_close( int iobase) +void irport_close(int iobase) { DEBUG(4, __FUNCTION__ "()\n"); @@ -142,7 +140,7 @@ outb(0, iobase+UART_MCR); /* Turn off interrupts */ - outb(0, iobase+UART_IER); + outb(0, iobase+UART_IER); } /* @@ -186,16 +184,22 @@ * more packets to send, we send them here. * */ -static void irport_write_wakeup( struct irda_device *idev) +static void irport_write_wakeup(struct irda_device *idev) { - int actual = 0, count; + int actual = 0; int iobase; ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); /* Finished with frame? */ - if (idev->tx_buff.offset == idev->tx_buff.len) { + if (idev->tx_buff.len > 0) { + /* Write data left in transmit buffer */ + actual = irport_write(idev->io.iobase2, idev->io.fifo_size, + idev->tx_buff.data, idev->tx_buff.len); + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; + } else { iobase = idev->io.iobase2; /* * Now serial buffer is almost free & we can start @@ -206,23 +210,14 @@ /* Schedule network layer, so we can get some more frames */ mark_bh(NET_BH); -#ifdef CONFIG_HALF_DUPLEX + outb(UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14 | UART_FCR_CLEAR_RCVR, iobase+UART_FCR); /* Enable FIFO's */ /* Turn on receive interrupts */ outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); -#endif - return; } - - /* Write data left in transmit buffer */ - count = idev->tx_buff.len - idev->tx_buff.offset; - actual = irport_write(idev->io.iobase2, idev->io.fifo_size, - idev->tx_buff.head, count); - idev->tx_buff.offset += actual; - idev->tx_buff.head += actual; } /* @@ -283,22 +278,19 @@ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; - /* - * Transfer skb to tx_buff while wrapping, stuffing and making CRC - */ + /* Init tx buffer */ + idev->tx_buff.data = idev->tx_buff.head; + + /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, idev->tx_buff.truesize); -/* actual = irport_write(idev->io.iobase2, idev->io.fifo_size, */ -/* idev->tx_buff.data, idev->tx_buff.len); */ - - idev->tx_buff.offset = actual; - idev->tx_buff.head = idev->tx_buff.data + actual; + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; -#ifdef CONFIG_HALF_DUPLEX /* Turn on transmit finished interrupt. Will fire immediately! */ outb(UART_IER_THRI, iobase+UART_IER); -#endif + dev_kfree_skb(skb); return 0; @@ -318,44 +310,37 @@ if (!idev) return; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); iobase = idev->io.iobase2; - if (idev->rx_buff.len == 0) - idev->rx_buff.head = idev->rx_buff.data; - /* * Receive all characters in Rx FIFO, unwrap and unstuff them. * async_unwrap_char will deliver all found frames */ do { - async_unwrap_char(idev, inb( iobase+UART_RX)); + async_unwrap_char(idev, inb(iobase+UART_RX)); /* Make sure we don't stay here to long */ if (boguscount++ > 32) { DEBUG(0,__FUNCTION__ "(), breaking!\n"); break; } - } while (inb(iobase+UART_LSR) & UART_LSR_DR); } /* * Function irport_interrupt (irq, dev_id, regs) * - * + * Interrupt handler */ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct irda_device *idev = (struct irda_device *) dev_id; - int iobase; int iir, lsr; int boguscount = 0; - DEBUG(5, __FUNCTION__ "(), irq %d\n", irq); - if (!idev) { printk(KERN_WARNING __FUNCTION__ "() irq %d for unknown device.\n", irq); @@ -368,19 +353,13 @@ iir = inb(iobase + UART_IIR) & UART_IIR_ID; while (iir) { - DEBUG(4,__FUNCTION__ "(), iir=%#x\n", iir); - /* Clear interrupt */ lsr = inb(iobase+UART_LSR); if ((iir & UART_IIR_THRI) && (lsr & UART_LSR_THRE)) { /* Transmitter ready for data */ irport_write_wakeup(idev); - } -#ifdef CONFIG_HALF_DUPLEX - else -#endif - if ((iir & UART_IIR_RDI) && (lsr & UART_LSR_DR)) { + } else if ((iir & UART_IIR_RDI) && (lsr & UART_LSR_DR)) { /* Receive interrupt */ irport_receive(idev); } @@ -393,7 +372,6 @@ } idev->netdev.interrupt = 0; } - #ifdef MODULE diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.2.6/linux/drivers/net/irda/irtty.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/irtty.c Sat Apr 24 17:49:37 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Tue Apr 6 21:35:25 1999 + * Modified at: Thu Apr 22 09:20:24 1999 * Modified by: Dag Brattli * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, @@ -45,22 +45,22 @@ static struct tty_ldisc irda_ldisc; -static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev); -static void irtty_wait_until_sent( struct irda_device *driver); -static int irtty_is_receiving( struct irda_device *idev); -static int irtty_net_init( struct device *dev); +static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev); +static void irtty_wait_until_sent(struct irda_device *driver); +static int irtty_is_receiving(struct irda_device *idev); +static int irtty_net_init(struct device *dev); static int irtty_net_open(struct device *dev); static int irtty_net_close(struct device *dev); -static int irtty_open( struct tty_struct *tty); -static void irtty_close( struct tty_struct *tty); -static int irtty_ioctl( struct tty_struct *, void *, int, void *); -static int irtty_receive_room( struct tty_struct *tty); -static void irtty_change_speed( struct irda_device *dev, int baud); -static void irtty_write_wakeup( struct tty_struct *tty); +static int irtty_open(struct tty_struct *tty); +static void irtty_close(struct tty_struct *tty); +static int irtty_ioctl(struct tty_struct *, void *, int, void *); +static int irtty_receive_room(struct tty_struct *tty); +static void irtty_change_speed(struct irda_device *dev, int baud); +static void irtty_write_wakeup(struct tty_struct *tty); -static void irtty_receive_buf( struct tty_struct *, const unsigned char *, - char *, int); +static void irtty_receive_buf(struct tty_struct *, const unsigned char *, + char *, int); char *driver_name = "irtty"; __initfunc(int irtty_init(void)) @@ -73,15 +73,15 @@ return -ENOMEM; } - dongles = hashbin_new( HB_LOCAL); - if ( dongles == NULL) { - printk( KERN_WARNING - "IrDA: Can't allocate dongles hashbin!\n"); + dongles = hashbin_new(HB_LOCAL); + if (dongles == NULL) { + printk(KERN_WARNING + "IrDA: Can't allocate dongles hashbin!\n"); return -ENOMEM; } /* Fill in our line protocol discipline, and register it */ - memset( &irda_ldisc, 0, sizeof( irda_ldisc)); + memset(&irda_ldisc, 0, sizeof( irda_ldisc)); irda_ldisc.magic = TTY_LDISC_MAGIC; irda_ldisc.name = "irda"; @@ -97,10 +97,10 @@ irda_ldisc.receive_room = irtty_receive_room; irda_ldisc.write_wakeup = irtty_write_wakeup; - if (( status = tty_register_ldisc( N_IRDA, &irda_ldisc)) != 0) { - printk( KERN_ERR - "IrDA: can't register line discipline (err = %d)\n", - status); + if (( status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) { + printk(KERN_ERR + "IrDA: can't register line discipline (err = %d)\n", + status); } return status; @@ -120,10 +120,10 @@ /* * Unregister tty line-discipline */ - if (( ret = tty_register_ldisc( N_IRDA, NULL))) { - printk( KERN_ERR - "IrTTY: can't unregister line discipline (err = %d)\n", - ret); + if ((ret = tty_register_ldisc(N_IRDA, NULL))) { + ERROR(__FUNCTION__ + "(), can't unregister line discipline (err = %d)\n", + ret); } /* @@ -131,8 +131,8 @@ * callback to irtty_close(), therefore we do give any deallocation * function to hashbin_destroy(). */ - hashbin_delete( irtty, NULL); - hashbin_delete( dongles, NULL); + hashbin_delete(irtty, NULL); + hashbin_delete(dongles, NULL); } #endif /* MODULE */ @@ -143,47 +143,45 @@ * discipline is called for. Because we are sure the tty line exists, * we only have to link it to a free IrDA channel. */ -static int irtty_open( struct tty_struct *tty) +static int irtty_open(struct tty_struct *tty) { struct irtty_cb *self; char name[16]; - ASSERT( tty != NULL, return -EEXIST;); + ASSERT(tty != NULL, return -EEXIST;); /* First make sure we're not already connected. */ self = (struct irtty_cb *) tty->disc_data; - if ( self != NULL && self->magic == IRTTY_MAGIC) + if (self != NULL && self->magic == IRTTY_MAGIC) return -EEXIST; /* * Allocate new instance of the driver */ - self = kmalloc( sizeof(struct irtty_cb), GFP_KERNEL); - if ( self == NULL) { - printk( KERN_ERR "IrDA: Can't allocate memory for " - "IrDA control block!\n"); + self = kmalloc(sizeof(struct irtty_cb), GFP_KERNEL); + if (self == NULL) { + printk(KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); return -ENOMEM; } - memset( self, 0, sizeof(struct irtty_cb)); + memset(self, 0, sizeof(struct irtty_cb)); self->tty = tty; tty->disc_data = self; /* Give self a name */ - sprintf( name, "%s%d", tty->driver.name, - MINOR(tty->device) - tty->driver.minor_start + - tty->driver.name_base); - + sprintf(name, "%s%d", tty->driver.name, + MINOR(tty->device) - tty->driver.minor_start + + tty->driver.name_base); + /* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */ - hashbin_insert( irtty, (QUEUE*) self, (int) self, NULL); + hashbin_insert(irtty, (QUEUE*) self, (int) self, NULL); - if (tty->driver.flush_buffer) { + if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); - } - - if (tty->ldisc.flush_buffer) { + + if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); - } self->magic = IRTTY_MAGIC; @@ -198,12 +196,12 @@ * that are not device dependent (such as link disconnect time) so * this parameter can be set by IrLAP (or the user) instead. DB */ - irda_init_max_qos_capabilies( &self->idev.qos); + irda_init_max_qos_capabilies(&self->idev.qos); /* The only value we must override it the baudrate */ self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200; - self->idev.qos.min_turn_time.bits = 0x03; + self->idev.qos.min_turn_time.bits = 0x0f; self->idev.flags = IFF_SIR | IFF_PIO; irda_qos_bits_to_value(&self->idev.qos); @@ -236,7 +234,7 @@ } /* - * Function irtty_close ( tty) + * Function irtty_close (tty) * * Close down a IrDA channel. This means flushing out any pending queues, * and then restoring the TTY line discipline to what it was before it got @@ -272,14 +270,40 @@ MOD_DEC_USE_COUNT; } +/* + * Function irtty_stop_receiver (irda_device, stop) + * + * + * + */ +static void irtty_stop_receiver(struct irda_device *idev, int stop) +{ + struct termios old_termios; + struct irtty_cb *self; + int cflag; + + self = (struct irtty_cb *) idev->priv; + + old_termios = *(self->tty->termios); + cflag = self->tty->termios->c_cflag; + + if (stop) + cflag &= ~CREAD; + else + cflag |= CREAD; + + self->tty->termios->c_cflag = cflag; + self->tty->driver.set_termios(self->tty, &old_termios); +} + /* - * Function irtty_change_speed ( self, baud) + * Function irtty_change_speed (self, baud) * * Change the speed of the serial port. The driver layer must check that * all transmission has finished using the irtty_wait_until_sent() * function. */ -static void irtty_change_speed( struct irda_device *idev, int baud) +static void irtty_change_speed(struct irda_device *idev, int baud) { struct termios old_termios; struct irtty_cb *self; @@ -287,22 +311,22 @@ DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); self = (struct irtty_cb *) idev->priv; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); old_termios = *(self->tty->termios); cflag = self->tty->termios->c_cflag; cflag &= ~CBAUD; - DEBUG( 4, __FUNCTION__ "(), Setting speed to %d\n", baud); + DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", baud); - switch( baud) { + switch (baud) { case 1200: cflag |= B1200; break; @@ -331,7 +355,7 @@ } self->tty->termios->c_cflag = cflag; - self->tty->driver.set_termios( self->tty, &old_termios); + self->tty->driver.set_termios(self->tty, &old_termios); } /* @@ -340,43 +364,42 @@ * Initialize attached dongle. Warning, must be called with a process * context! */ -static void irtty_init_dongle( struct irtty_cb *self, int type) +static void irtty_init_dongle(struct irtty_cb *self, int type) { struct dongle_q *node; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); #ifdef CONFIG_KMOD /* Try to load the module needed */ switch( type) { case ESI_DONGLE: - DEBUG( 0, __FUNCTION__ "(), ESI dongle!\n"); - request_module( "esi"); + MESSAGE("IrDA: Trying to initialize ESI dongle!\n"); + request_module("esi"); break; case TEKRAM_DONGLE: - DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n"); - request_module( "tekram"); + MESSAGE("IrDA: Trying to initialize Tekram dongle!\n"); + request_module("tekram"); break; case ACTISYS_DONGLE: /* FALLTHROUGH */ case ACTISYS_PLUS_DONGLE: - DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n"); - request_module( "actisys"); + MESSAGE("IrDA: Trying to initialize ACTiSYS dongle!\n"); + request_module("actisys"); break; case GIRBIL_DONGLE: - DEBUG( 0, __FUNCTION__ "(), GIrBIL dongle!\n"); - request_module( "girbil"); + MESSAGE("IrDA: Trying to initialize GIrBIL dongle!\n"); + request_module("girbil"); break; default: - DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n"); + ERROR("Unknown dongle type!\n"); return; - break; } #endif /* CONFIG_KMOD */ - node = hashbin_find( dongles, type, NULL); + node = hashbin_find(dongles, type, NULL); if ( !node) { - DEBUG(0, __FUNCTION__ "(), Unable to find requested dongle\n"); + ERROR("Unable to find requested dongle\n"); return; } self->dongle_q = node; @@ -387,14 +410,14 @@ /* * Now initialize the dongle! */ - node->dongle->open( &self->idev, type); - node->dongle->qos_init( &self->idev, &self->idev.qos); + node->dongle->open(&self->idev, type); + node->dongle->qos_init(&self->idev, &self->idev.qos); /* Reset dongle */ - node->dongle->reset( &self->idev, 0); + node->dongle->reset(&self->idev, 0); /* Set to default baudrate */ - node->dongle->change_speed( &self->idev, 9600); + node->dongle->change_speed(&self->idev, 9600); } /* @@ -411,25 +434,25 @@ self = (struct irtty_cb *) tty->disc_data; - ASSERT( self != NULL, return -ENODEV;); - ASSERT( self->magic == IRTTY_MAGIC, return -EBADR;); + ASSERT(self != NULL, return -ENODEV;); + ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;); - if ( _IOC_DIR(cmd) & _IOC_READ) + if (_IOC_DIR(cmd) & _IOC_READ) err = verify_area( VERIFY_WRITE, (void *) arg, size); - else if ( _IOC_DIR(cmd) & _IOC_WRITE) + else if (_IOC_DIR(cmd) & _IOC_WRITE) err = verify_area( VERIFY_READ, (void *) arg, size); - if ( err) + if (err) return err; switch(cmd) { case TCGETS: case TCGETA: - return n_tty_ioctl( tty, (struct file *) file, cmd, - (unsigned long) arg); + return n_tty_ioctl(tty, (struct file *) file, cmd, + (unsigned long) arg); break; case IRTTY_IOCTDONGLE: /* Initialize dongle */ - irtty_init_dongle( self, (int) arg); + irtty_init_dongle(self, (int) arg); break; default: return -ENOIOCTLCMD; @@ -450,8 +473,8 @@ { struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); /* Read the characters out of the buffer */ while (count--) { @@ -461,19 +484,19 @@ if (fp && *fp++) { DEBUG( 0, "Framing or parity error!\n"); irda_device_set_media_busy( &self->idev, TRUE); - /* sl->rx_errors++; */ + cp++; continue; } /* Unwrap and destuff one byte */ - async_unwrap_char( &self->idev, *cp++); + async_unwrap_char(&self->idev, *cp++); } } /* * Function irtty_hard_xmit (skb, dev) * - * Transmit skb + * Transmit frame * */ static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev) @@ -482,9 +505,6 @@ struct irda_device *idev; int actual = 0; - ASSERT( dev != NULL, return 0;); - ASSERT( skb != NULL, return 0;); - idev = (struct irda_device *) dev->priv; ASSERT(idev != NULL, return 0;); @@ -498,10 +518,11 @@ /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; - - /* - * Transfer skb to tx_buff while wrapping, stuffing and making CRC - */ + + /* Init tx buffer*/ + idev->tx_buff.data = idev->tx_buff.head; + + /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, idev->tx_buff.truesize); @@ -509,13 +530,14 @@ dev->trans_start = jiffies; - if ( self->tty->driver.write) + if (self->tty->driver.write) actual = self->tty->driver.write(self->tty, 0, idev->tx_buff.data, idev->tx_buff.len); - idev->tx_buff.offset = actual; - idev->tx_buff.head = idev->tx_buff.data + actual; + /* Hide the part we just transmitted */ + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; idev->stats.tx_packets++; idev->stats.tx_bytes += idev->tx_buff.len; @@ -524,7 +546,7 @@ * Did we transmit the whole frame? Commented out for now since * I must check if this optimalization really works. DB. */ - if (( idev->tx.count - idev->tx.ptr) <= 0) { + if ((idev->tx_buff.len) == 0) { DEBUG( 4, "irtty_xmit_buf: finished with frame!\n"); self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); irda_unlock( &self->tbusy); @@ -541,8 +563,9 @@ * Used by the TTY to find out how much data we can receive at a time * */ -static int irtty_receive_room( struct tty_struct *tty) +static int irtty_receive_room(struct tty_struct *tty) { + DEBUG(0, __FUNCTION__ "()\n"); return 65536; /* We can handle an infinite amount of data. :-) */ } @@ -553,47 +576,42 @@ * more packets to send, we send them here. * */ -static void irtty_write_wakeup( struct tty_struct *tty) +static void irtty_write_wakeup(struct tty_struct *tty) { - int actual = 0, count; struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; struct irda_device *idev; + int actual = 0; /* * First make sure we're connected. */ - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); idev = &self->idev; - /* - * Finished with frame? - */ - if ( idev->tx_buff.offset == idev->tx_buff.len) { - + /* Finished with frame? */ + if (idev->tx_buff.len > 0) { + /* Write data left in transmit buffer */ + actual = tty->driver.write(tty, 0, idev->tx_buff.data, + idev->tx_buff.len); + + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; + } else { /* * Now serial buffer is almost free & we can start * transmission of another packet */ DEBUG(5, __FUNCTION__ "(), finished with frame!\n"); - + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); idev->netdev.tbusy = 0; /* Unlock */ - + /* Tell network layer that we want more frames */ - mark_bh( NET_BH); - - return; + mark_bh(NET_BH); } - /* - * Write data left in transmit buffer - */ - count = idev->tx_buff.len - idev->tx_buff.offset; - actual = tty->driver.write( tty, 0, idev->tx_buff.head, count); - idev->tx_buff.offset += actual; - idev->tx_buff.head += actual; } /* @@ -602,9 +620,9 @@ * Return TRUE is we are currently receiving a frame * */ -static int irtty_is_receiving( struct irda_device *idev) +static int irtty_is_receiving(struct irda_device *idev) { - return ( idev->rx_buff.state != OUTSIDE_FRAME); + return (idev->rx_buff.state != OUTSIDE_FRAME); } /* @@ -614,20 +632,20 @@ * to change the speed of the serial port. Warning this function must * be called with a process context! */ -static void irtty_wait_until_sent( struct irda_device *idev) +static void irtty_wait_until_sent(struct irda_device *idev) { struct irtty_cb *self = (struct irtty_cb *) idev->priv; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); - DEBUG( 4, "Chars in buffer %d\n", - self->tty->driver.chars_in_buffer( self->tty)); + DEBUG(4, "Chars in buffer %d\n", + self->tty->driver.chars_in_buffer(self->tty)); - tty_wait_until_sent( self->tty, 0); + tty_wait_until_sent(self->tty, 0); } -int irtty_register_dongle( struct dongle *dongle) +int irtty_register_dongle(struct dongle *dongle) { struct dongle_q *new; @@ -638,12 +656,11 @@ } /* Make new IrDA dongle */ - new = (struct dongle_q *)kmalloc(sizeof(struct dongle_q), GFP_KERNEL); - if (new == NULL) { - return 1; + new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL); + if (new == NULL) + return -1; - } - memset( new, 0, sizeof( struct dongle_q)); + memset(new, 0, sizeof( struct dongle_q)); new->dongle = dongle; /* Insert IrDA dongle into hashbin */ @@ -652,16 +669,16 @@ return 0; } -void irtty_unregister_dongle( struct dongle *dongle) +void irtty_unregister_dongle(struct dongle *dongle) { struct dongle_q *node; - node = hashbin_remove( dongles, dongle->type, NULL); - if ( !node) { - DEBUG( 0, __FUNCTION__ "(), dongle not found!\n"); + node = hashbin_remove(dongles, dongle->type, NULL); + if (!node) { + ERROR(__FUNCTION__ "(), dongle not found!\n"); return; } - kfree( node); + kfree(node); } @@ -696,26 +713,24 @@ set_fs(get_ds()); if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { - DEBUG(0, __FUNCTION__ "(), error!\n"); + ERROR(__FUNCTION__ "(), error doing ioctl!\n"); } set_fs(fs); } - -static int irtty_net_init( struct device *dev) +static int irtty_net_init(struct device *dev) { /* Set up to be a normal IrDA network device driver */ - irda_device_setup( dev); + irda_device_setup(dev); /* Insert overrides below this line! */ return 0; } - -static int irtty_net_open( struct device *dev) +static int irtty_net_open(struct device *dev) { - ASSERT( dev != NULL, return -1;); + ASSERT(dev != NULL, return -1;); /* Ready to play! */ dev->tbusy = 0; @@ -729,7 +744,7 @@ static int irtty_net_close(struct device *dev) { - ASSERT( dev != NULL, return -1;); + ASSERT(dev != NULL, return -1;); /* Stop device */ dev->tbusy = 1; diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c --- v2.2.6/linux/drivers/net/irda/pc87108.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/pc87108.c Sat Apr 24 17:49:37 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Sat Apr 3 15:54:47 1999 + * Modified at: Tue Apr 20 11:11:39 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli @@ -734,10 +734,9 @@ /* Decide if we should use PIO or DMA transfer */ if ( idev->io.baudrate > 115200) { - memcpy( idev->tx_buff.data, skb->data, skb->len); + idev->tx_buff.data = idev->tx_buff.head; + memcpy(idev->tx_buff.data, skb->data, skb->len); idev->tx_buff.len = skb->len; - idev->tx_buff.head = idev->tx_buff.data; - idev->tx_buff.offset = 0; mtt = irda_get_mtt( skb); if ( mtt > 50) { @@ -767,11 +766,10 @@ pc87108_dma_write( idev, iobase); } } else { - idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, - idev->tx_buff.truesize); + idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, + idev->tx_buff.truesize); - idev->tx_buff.offset = 0; - idev->tx_buff.head = idev->tx_buff.data; + idev->tx_buff.data = idev->tx_buff.head; /* Add interrupt on tx low level (will fire immediately) */ switch_bank( iobase, BANK0); @@ -945,8 +943,7 @@ /* driver->media_busy = FALSE; */ idev->io.direction = IO_RECV; - idev->rx_buff.head = idev->rx_buff.data; - idev->rx_buff.offset = 0; + idev->rx_buff.data = idev->rx_buff.head; /* Reset Rx FIFO. This will also flush the ST_FIFO */ outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); @@ -1024,42 +1021,41 @@ /* Skip frame */ idev->stats.rx_errors++; - idev->rx_buff.offset += len; - idev->rx_buff.head += len; + idev->rx_buff.data += len; - if ( status & FRM_ST_MAX_LEN) + if (status & FRM_ST_MAX_LEN) idev->stats.rx_length_errors++; - if ( status & FRM_ST_PHY_ERR) + if (status & FRM_ST_PHY_ERR) idev->stats.rx_frame_errors++; - if ( status & FRM_ST_BAD_CRC) + if (status & FRM_ST_BAD_CRC) idev->stats.rx_crc_errors++; } /* The errors below can be reported in both cases */ - if ( status & FRM_ST_OVR1) + if (status & FRM_ST_OVR1) idev->stats.rx_fifo_errors++; - if ( status & FRM_ST_OVR2) + if (status & FRM_ST_OVR2) idev->stats.rx_fifo_errors++; } else { /* Check if we have transfered all data to memory */ - if ( inb( iobase+LSR) & LSR_RXDA) { + if (inb(iobase+LSR) & LSR_RXDA) { /* Put this entry back in fifo */ st_fifo->head--; st_fifo->len++; st_fifo->entries[st_fifo->head].status = status; - st_fifo->entries[ st_fifo->head].len = len; + st_fifo->entries[st_fifo->head].len = len; /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return FALSE; /* I'll be back! */ } /* Should be OK then */ - skb = dev_alloc_skb( len+1); + skb = dev_alloc_skb(len+1); if (skb == NULL) { printk( KERN_INFO __FUNCTION__ "(), memory squeeze, dropping frame.\n"); @@ -1070,20 +1066,19 @@ } /* Make sure IP header gets aligned */ - skb_reserve( skb, 1); + skb_reserve(skb, 1); /* Copy frame without CRC */ - if ( idev->io.baudrate < 4000000) { - skb_put( skb, len-2); - memcpy( skb->data, idev->rx_buff.head, len-2); + if (idev->io.baudrate < 4000000) { + skb_put(skb, len-2); + memcpy(skb->data, idev->rx_buff.data, len-2); } else { - skb_put( skb, len-4); - memcpy( skb->data, idev->rx_buff.head, len-4); + skb_put(skb, len-4); + memcpy(skb->data, idev->rx_buff.data, len-4); } /* Move to next frame */ - idev->rx_buff.offset += len; - idev->rx_buff.head += len; + idev->rx_buff.data += len; idev->stats.rx_packets++; skb->dev = &idev->netdev; @@ -1093,7 +1088,7 @@ } } /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return TRUE; } @@ -1109,23 +1104,19 @@ __u8 byte = 0x00; int iobase; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); iobase = idev->io.iobase; - if ( idev->rx_buff.len == 0) { - idev->rx_buff.head = idev->rx_buff.data; - } - /* Receive all characters in Rx FIFO */ do { - byte = inb( iobase+RXD); - async_unwrap_char( idev, byte); + byte = inb(iobase+RXD); + async_unwrap_char(idev, byte); - } while ( inb( iobase+LSR) & LSR_RXDA); /* Data available */ + } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */ } /* @@ -1134,38 +1125,35 @@ * Handle SIR interrupt * */ -static __u8 pc87108_sir_interrupt( struct irda_device *idev, int eir) +static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir) { - int len; int actual; __u8 new_ier = 0; /* Transmit FIFO low on data */ if ( eir & EIR_TXLDL_EV) { /* Write data left in transmit buffer */ - len = idev->tx_buff.len - idev->tx_buff.offset; - - ASSERT( len > 0, return 0;); - actual = pc87108_pio_write( idev->io.iobase, - idev->tx_buff.head, - len, idev->io.fifo_size); - idev->tx_buff.offset += actual; - idev->tx_buff.head += actual; + actual = pc87108_pio_write(idev->io.iobase, + idev->tx_buff.data, + idev->tx_buff.len, + idev->io.fifo_size); + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; idev->io.direction = IO_XMIT; - ASSERT( actual <= len, return 0;); /* Check if finished */ - if ( actual == len) { - DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + if (idev->tx_buff.len > 0) + new_ier |= IER_TXLDL_IE; + else { idev->netdev.tbusy = 0; /* Unlock */ idev->stats.tx_packets++; - + mark_bh(NET_BH); new_ier |= IER_TXEMP_IE; - } else - new_ier |= IER_TXLDL_IE; + } + } /* Check if transmission has completed */ if ( eir & EIR_TXEMP_EV) { diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c --- v2.2.6/linux/drivers/net/irda/tekram.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/tekram.c Sat Apr 24 17:49:37 1999 @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: tekram.c - * Version: 0.5 + * Version: 1.0 * Description: Implementation of the Tekram IrMate IR-210B dongle * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Mon Feb 15 14:13:17 1999 + * Modified at: Tue Apr 13 16:33:54 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -33,16 +33,23 @@ #include #include -#include #include #include #include -static void tekram_reset( struct irda_device *dev, int unused); -static void tekram_open( struct irda_device *dev, int type); -static void tekram_close( struct irda_device *dev); -static void tekram_change_speed( struct irda_device *dev, int baud); -static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos); +static void tekram_reset(struct irda_device *dev, int unused); +static void tekram_open(struct irda_device *dev, int type); +static void tekram_close(struct irda_device *dev); +static void tekram_change_speed(struct irda_device *dev, int baud); +static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos); + +#define TEKRAM_115200 0x00 +#define TEKRAM_57600 0x01 +#define TEKRAM_38400 0x02 +#define TEKRAM_19200 0x03 +#define TEKRAM_9600 0x04 + +#define TEKRAM_PW 0x10 /* Pulse select bit */ static struct dongle dongle = { TEKRAM_DONGLE, @@ -53,9 +60,9 @@ tekram_init_qos, }; -__initfunc(void tekram_init(void)) +__initfunc(int tekram_init(void)) { - irtty_register_dongle( &dongle); + return irtty_register_dongle(&dongle); } void tekram_cleanup(void) @@ -102,17 +109,17 @@ int cflag; __u8 byte; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( dev != NULL, return;); - ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(dev != NULL, return;); + ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); self = (struct irtty_cb *) dev->priv; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); - if ( !self->tty) + if (!self->tty) return; tty = self->tty; @@ -123,26 +130,27 @@ cflag &= ~CBAUD; switch (baud) { - case 9600: default: + /* FALLTHROUGH */ + case 9600: cflag |= B9600; - byte = 4; + byte = TEKRAM_PW|TEKRAM_9600; break; case 19200: cflag |= B19200; - byte = 3; + byte = TEKRAM_PW|TEKRAM_19200; break; case 34800: cflag |= B38400; - byte = 2; + byte = TEKRAM_PW|TEKRAM_38400; break; case 57600: cflag |= B57600; - byte = 1; + byte = TEKRAM_PW|TEKRAM_57600; break; case 115200: cflag |= B115200; - byte = 0; + byte = TEKRAM_PW|TEKRAM_115200; break; } @@ -150,22 +158,22 @@ irtty_set_dtr_rts(tty, TRUE, FALSE); /* Wait at least 7us */ - udelay( 7); + udelay(7); /* Write control byte */ - if ( tty->driver.write) - tty->driver.write( self->tty, 0, &byte, 1); + if (tty->driver.write) + tty->driver.write(self->tty, 0, &byte, 1); /* Wait at least 100 ms */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout( 10); + schedule_timeout(MSECS_TO_JIFFIES(100)); /* Set DTR, Set RTS */ irtty_set_dtr_rts(tty, TRUE, TRUE); /* Now change the speed of the serial port */ tty->termios->c_cflag = cflag; - tty->driver.set_termios( tty, &old_termios); + tty->driver.set_termios(tty, &old_termios); } /* @@ -175,30 +183,29 @@ * must be called with a process context!! * * Algorithm: - * 0. set RTS and DTR, and wait 50 ms - * ( power off the IR-210 ) + * 0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 ) * 1. clear RTS * 2. set DTR, and wait at least 1 ms * 3. clear DTR to SPACE state, wait at least 50 us for further * operation */ -void tekram_reset( struct irda_device *dev, int unused) +void tekram_reset(struct irda_device *dev, int unused) { struct irtty_cb *self; struct tty_struct *tty; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( dev != NULL, return;); - ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(dev != NULL, return;); + ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); self = (struct irtty_cb *) dev->priv; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRTTY_MAGIC, return;); tty = self->tty; - if ( !tty) + if (!tty) return; /* Power off dongle */ @@ -206,18 +213,20 @@ /* Sleep 50 ms */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(5); + schedule_timeout(MSECS_TO_JIFFIES(50)); /* Clear DTR, Set RTS */ irtty_set_dtr_rts(tty, FALSE, TRUE); /* Should sleep 1 ms, but 10-20 should not do any harm */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(2); + schedule_timeout(MSECS_TO_JIFFIES(20)); /* Set DTR, Set RTS */ irtty_set_dtr_rts(tty, TRUE, TRUE); + udelay(50); + /* Finished! */ } @@ -227,10 +236,11 @@ * Initialize QoS capabilities * */ -static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos) +static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */ + qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ + irda_qos_bits_to_value(qos); } #ifdef MODULE @@ -246,8 +256,7 @@ */ int init_module(void) { - tekram_init(); - return(0); + return tekram_init(); } /* diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c --- v2.2.6/linux/drivers/net/irda/uircc.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/uircc.c Sat Apr 24 17:49:37 1999 @@ -7,7 +7,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Dec 26 10:59:03 1998 - * Modified at: Sat Apr 3 15:54:41 1999 + * Modified at: Tue Apr 20 11:15:52 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -190,7 +190,7 @@ /* The only value we must override it the baudrate */ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| - IR_115200|/*IR_576000|IR_1152000| */(IR_4000000 << 8); + IR_115200/*IR_576000|IR_1152000 |(IR_4000000 << 8)*/; idev->qos.min_turn_time.bits = 0x0f; irda_qos_bits_to_value(&idev->qos); @@ -372,7 +372,7 @@ DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); /* Set self pole address */ - outb(0x10, iobase+UIRCC_CR8); + //outb(0xfe, iobase+UIRCC_CR8); /* outb(0x10, iobase+UIRCC_CR11); */ break; @@ -443,8 +443,7 @@ skb->len++; idev->tx_buff.len = skb->len; - idev->tx_buff.head = idev->tx_buff.data; - idev->tx_buff.offset = 0; + idev->tx_buff.data = idev->tx_buff.head; mtt = irda_get_mtt(skb); @@ -586,11 +585,15 @@ outb(self->cr3, iobase+UIRCC_CR3); /* Transmit reset (just in case) */ - outb(UIRCC_CR0_XMIT_RST, iobase+UIRCC_CR0); + outb(UIRCC_CR0_XMIT_RST|0x17, iobase+UIRCC_CR0); /* Set modem */ outb(0x08, iobase+UIRCC_CR10); + /* Enable receiving with CRC */ + self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN); + outb(self->cr3, iobase+UIRCC_CR3); + /* Make sure Rx DMA is set */ outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_MUST_SET, iobase+UIRCC_CR1); @@ -602,13 +605,13 @@ /* driver->media_busy = FALSE; */ idev->io.direction = IO_RECV; - idev->rx_buff.head = idev->rx_buff.data; - idev->rx_buff.offset = 0; + idev->rx_buff.data = idev->rx_buff.head; +#if 0 /* Enable receiving with CRC */ self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN); outb(self->cr3, iobase+UIRCC_CR3); - +#endif DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3); /* Address check? */ @@ -673,7 +676,7 @@ /* } */ skb_put(skb, len); - memcpy(skb->data, idev->rx_buff.head, len); + memcpy(skb->data, idev->rx_buff.data, len); idev->stats.rx_packets++; skb->dev = &idev->netdev; @@ -737,7 +740,7 @@ uircc_dma_xmit_complete(idev, FALSE); uircc_dma_receive(idev); - /* outb(0, iobase+UIRCC_CR2); */ + outb(0x0d, iobase+UIRCC_CR2); break; case UIRCC_SR3_TMR_OUT: /* Disable timer */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- v2.2.6/linux/drivers/net/irda/w83977af_ir.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/w83977af_ir.c Sat Apr 24 17:49:37 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Paul VanderSpek * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Wed Apr 7 17:35:59 1999 + * Modified at: Tue Apr 20 11:15:00 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Corel Computer Corp. @@ -482,8 +482,7 @@ if (idev->io.baudrate > 115200) { memcpy(idev->tx_buff.data, skb->data, skb->len); idev->tx_buff.len = skb->len; - idev->tx_buff.head = idev->tx_buff.data; - idev->tx_buff.offset = 0; + idev->tx_buff.data = idev->tx_buff.head; mtt = irda_get_mtt(skb); if (mtt > 50) { @@ -512,20 +511,18 @@ w83977af_dma_write(idev, iobase); } } else { + idev->tx_buff.data = idev->tx_buff.head; idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, idev->tx_buff.truesize); - idev->tx_buff.offset = 0; - idev->tx_buff.head = idev->tx_buff.data; - /* Add interrupt on tx low level (will fire immediately) */ - switch_bank( iobase, SET0); + switch_bank(iobase, SET0); outb(ICR_ETXTHI, iobase+ICR); } dev_kfree_skb(skb); /* Restore set register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); return 0; } @@ -594,9 +591,9 @@ } /* Fill FIFO with current frame */ - while (( fifo_size-- > 0) && (actual < len)) { + while ((fifo_size-- > 0) && (actual < len)) { /* Transmit next byte */ - outb( buf[actual++], iobase+TBR); + outb(buf[actual++], iobase+TBR); } DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", @@ -702,8 +699,7 @@ #endif /* driver->media_busy = FALSE; */ idev->io.direction = IO_RECV; - idev->rx_buff.head = idev->rx_buff.data; - idev->rx_buff.offset = 0; + idev->rx_buff.data = idev->rx_buff.head; /* * Reset Rx FIFO. This will also flush the ST_FIFO, it's very @@ -751,30 +747,30 @@ __u8 set; __u8 status; - DEBUG( 0, __FUNCTION__ "\n"); + DEBUG(0, __FUNCTION__ "\n"); iobase = idev->io.iobase; /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); iobase = idev->io.iobase; switch_bank(iobase, SET5); - if ( prev.status & FS_FO_FSFDR) { + if (prev.status & FS_FO_FSFDR) { status = prev.status; len = prev.len; - + prev.status = 0; } else { - status = inb( iobase+FS_FO); - len = inb( iobase+RFLFL); - len |= inb( iobase+RFLFH) << 8; + status = inb(iobase+FS_FO); + len = inb(iobase+RFLFL); + len |= inb(iobase+RFLFH) << 8; } - while ( status & FS_FO_FSFDR) { + while (status & FS_FO_FSFDR) { /* Check for errors */ - if ( status & FS_FO_ERR_MSK) { + if (status & FS_FO_ERR_MSK) { if ( status & FS_FO_LST_FR) { /* Add number of lost frames to stats */ idev->stats.rx_errors += len; @@ -782,29 +778,28 @@ /* Skip frame */ idev->stats.rx_errors++; - idev->rx_buff.offset += len; - idev->rx_buff.head += len; + idev->rx_buff.data += len; - if ( status & FS_FO_MX_LEX) + if (status & FS_FO_MX_LEX) idev->stats.rx_length_errors++; - if ( status & FS_FO_PHY_ERR) + if (status & FS_FO_PHY_ERR) idev->stats.rx_frame_errors++; - if ( status & FS_FO_CRC_ERR) + if (status & FS_FO_CRC_ERR) idev->stats.rx_crc_errors++; } /* The errors below can be reported in both cases */ - if ( status & FS_FO_RX_OV) + if (status & FS_FO_RX_OV) idev->stats.rx_fifo_errors++; - if ( status & FS_FO_FSF_OV) + if (status & FS_FO_FSF_OV) idev->stats.rx_fifo_errors++; } else { /* Check if we have transfered all data to memory */ switch_bank(iobase, SET0); - if ( inb( iobase+USR) & USR_RDR) { + if (inb(iobase+USR) & USR_RDR) { /* Put this entry back in fifo */ prev.status = status; prev.len = len; @@ -815,31 +810,30 @@ return FALSE; /* I'll be back! */ } - skb = dev_alloc_skb( len+1); + skb = dev_alloc_skb(len+1); if (skb == NULL) { - printk( KERN_INFO __FUNCTION__ - "(), memory squeeze, dropping frame.\n"); + printk(KERN_INFO __FUNCTION__ + "(), memory squeeze, dropping frame.\n"); /* Restore set register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); return FALSE; } /* Align to 20 bytes */ - skb_reserve( skb, 1); + skb_reserve(skb, 1); /* Copy frame without CRC */ if ( idev->io.baudrate < 4000000) { skb_put( skb, len-2); - memcpy( skb->data, idev->rx_buff.head, len-2); + memcpy( skb->data, idev->rx_buff.data, len-2); } else { skb_put( skb, len-4); - memcpy( skb->data, idev->rx_buff.head, len-4); + memcpy( skb->data, idev->rx_buff.data, len-4); } /* Move to next frame */ - idev->rx_buff.offset += len; - idev->rx_buff.head += len; + idev->rx_buff.data += len; skb->dev = &idev->netdev; skb->mac.raw = skb->data; @@ -854,7 +848,7 @@ len |= inb( iobase+RFLFH) << 8; } /* Restore set register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); return TRUE; } @@ -865,28 +859,24 @@ * Receive all data in receiver FIFO * */ -static void w83977af_pio_receive( struct irda_device *idev) +static void w83977af_pio_receive(struct irda_device *idev) { __u8 byte = 0x00; int iobase; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); iobase = idev->io.iobase; - if ( idev->rx_buff.len == 0) { - idev->rx_buff.head = idev->rx_buff.data; - } - /* Receive all characters in Rx FIFO */ do { - byte = inb( iobase+RBR); - async_unwrap_char( idev, byte); + byte = inb(iobase+RBR); + async_unwrap_char(idev, byte); - } while ( inb( iobase+USR) & USR_RDR); /* Data available */ + } while (inb(iobase+USR) & USR_RDR); /* Data available */ } /* @@ -897,7 +887,6 @@ */ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) { - int len; int actual; __u8 new_icr = 0; @@ -906,19 +895,19 @@ /* Transmit FIFO low on data */ if (isr & ISR_TXTH_I) { /* Write data left in transmit buffer */ - len = idev->tx_buff.len - idev->tx_buff.offset; - - ASSERT(len > 0, return 0;); actual = w83977af_pio_write(idev->io.iobase, - idev->tx_buff.head, - len, idev->io.fifo_size); - idev->tx_buff.offset += actual; - idev->tx_buff.head += actual; + idev->tx_buff.data, + idev->tx_buff.len, + idev->io.fifo_size); + idev->tx_buff.data += actual; + idev->tx_buff.len -= actual; idev->io.direction = IO_XMIT; - ASSERT( actual <= len, return 0;); + /* Check if finished */ - if ( actual == len) { + if (idev->tx_buff.len > 0) + new_icr |= ICR_ETXTHI; + else { DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); idev->netdev.tbusy = 0; /* Unlock */ idev->stats.tx_packets++; @@ -927,8 +916,8 @@ mark_bh(NET_BH); new_icr |= ICR_ETBREI; - } else - new_icr |= ICR_ETXTHI; + } + } /* Check if transmission has completed */ if (isr & ISR_TXEMP_I) { diff -u --recursive --new-file v2.2.6/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.2.6/linux/drivers/net/net_init.c Tue Dec 22 14:16:55 1998 +++ linux/drivers/net/net_init.c Sat Apr 24 17:51:48 1999 @@ -252,6 +252,22 @@ return dev; } + +void unregister_hipdev(struct device *dev) +{ + int i; + rtnl_lock(); + unregister_netdevice(dev); + for (i = 0; i < MAX_HIP_CARDS; ++i) { + if (hipdev_index[i] == dev) { + hipdev_index[i] = NULL; + break; + } + } + rtnl_unlock(); +} + + static int hippi_neigh_setup_dev(struct device *dev, struct neigh_parms *p) { /* Never send broadcast/multicast ARP messages */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.2.6/linux/drivers/net/pcnet32.c Tue Jan 19 11:32:51 1999 +++ linux/drivers/net/pcnet32.c Sat Apr 24 17:51:48 1999 @@ -13,7 +13,7 @@ * This driver is for PCnet32 and PCnetPCI based ethercards */ -static const char *version = "pcnet32.c:v1.11 17.1.99 tsbogend@alpha.franken.de\n"; +static const char *version = "pcnet32.c:v1.21 31.3.99 tsbogend@alpha.franken.de\n"; #include #include @@ -58,9 +58,36 @@ #define PORT_PORTSEL 0x03 #define PORT_ASEL 0x04 +#define PORT_100 0x40 #define PORT_FD 0x80 -static int options = PORT_ASEL; /* port selection */ + +/* + * table to translate option values from tulip + * to internal options + */ +static unsigned char options_mapping[] = { + PORT_ASEL, /* 0 Auto-select */ + PORT_AUI, /* 1 BNC/AUI */ + PORT_AUI, /* 2 AUI/BNC */ + PORT_ASEL, /* 3 not supported */ + PORT_10BT | PORT_FD, /* 4 10baseT-FD */ + PORT_ASEL, /* 5 not supported */ + PORT_ASEL, /* 6 not supported */ + PORT_ASEL, /* 7 not supported */ + PORT_ASEL, /* 8 not supported */ + PORT_MII, /* 9 MII 10baseT */ + PORT_MII | PORT_FD, /* 10 MII 10baseT-FD */ + PORT_MII, /* 11 MII (autosel) */ + PORT_10BT, /* 12 10BaseT */ + PORT_MII | PORT_100, /* 13 MII 100BaseTx */ + PORT_MII | PORT_100 | PORT_FD, /* 14 MII 100BaseTx-FD */ + PORT_ASEL /* 15 not supported */ +}; + +#define MAX_UNITS 8 +static int options[MAX_UNITS] = {0, }; +static int full_duplex[MAX_UNITS] = {0, }; /* * Theory of Operation @@ -116,6 +143,12 @@ * added port selection for modules * detect special T1/E1 WAN card and setup port selection * v1.11: fixed wrong checking of Tx errors + * v1.20: added check of return value kmalloc (cpeterso@cs.washington.edu) + * added save original kmalloc addr for freeing (mcr@solidum.com) + * added support for PCnetHome chip (joe@MIT.EDU) + * rewritten PCI card detection + * added dwio mode to get driver working on some PPC machines + * v1.21: added mii selection and mii ioctl */ @@ -140,202 +173,402 @@ #define PKT_BUF_SZ 1544 /* Offsets from base I/O address. */ -#define PCNET32_DATA 0x10 -#define PCNET32_ADDR 0x12 -#define PCNET32_RESET 0x14 -#define PCNET32_BUS_IF 0x16 -#define PCNET32_TOTAL_SIZE 0x18 +#define PCNET32_WIO_RDP 0x10 +#define PCNET32_WIO_RAP 0x12 +#define PCNET32_WIO_RESET 0x14 +#define PCNET32_WIO_BDP 0x16 + +#define PCNET32_DWIO_RDP 0x10 +#define PCNET32_DWIO_RAP 0x14 +#define PCNET32_DWIO_RESET 0x18 +#define PCNET32_DWIO_BDP 0x1C + +#define PCNET32_TOTAL_SIZE 0x20 #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; }; struct pcnet32_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; }; - /* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; - /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; + /* Receive and transmit ring base, along with extra bits. */ + u32 rx_ring; + u32 tx_ring; +}; + +/* PCnet32 access functions */ +struct pcnet32_access { + u16 (*read_csr)(unsigned long, int); + void (*write_csr)(unsigned long, int, u16); + u16 (*read_bcr)(unsigned long, int); + void (*write_bcr)(unsigned long, int, u16); + u16 (*read_rap)(unsigned long); + void (*write_rap)(unsigned long, u16); + void (*reset)(unsigned long); }; struct pcnet32_private { - /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ - struct pcnet32_rx_head rx_ring[RX_RING_SIZE]; - struct pcnet32_tx_head tx_ring[TX_RING_SIZE]; - struct pcnet32_init_block init_block; - const char *name; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff *tx_skbuff[TX_RING_SIZE]; - struct sk_buff *rx_skbuff[RX_RING_SIZE]; - int cur_rx, cur_tx; /* The next free ring entry */ - int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - char tx_full; - int options; - int shared_irq:1, /* shared irq possible */ - full_duplex:1; /* full duplex possible */ + /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ + struct pcnet32_rx_head rx_ring[RX_RING_SIZE]; + struct pcnet32_tx_head tx_ring[TX_RING_SIZE]; + struct pcnet32_init_block init_block; + const char *name; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff *tx_skbuff[TX_RING_SIZE]; + struct sk_buff *rx_skbuff[RX_RING_SIZE]; + struct pcnet32_access a; + void *origmem; + int cur_rx, cur_tx; /* The next free ring entry */ + int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + char tx_full; + int options; + int shared_irq:1, /* shared irq possible */ + full_duplex:1, /* full duplex possible */ + mii:1; /* mii port available */ #ifdef MODULE - struct device *next; + struct device *next; #endif }; -int pcnet32_probe(struct device *dev); -static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared); -static int pcnet32_open(struct device *dev); -static int pcnet32_init_ring(struct device *dev); -static int pcnet32_start_xmit(struct sk_buff *skb, struct device *dev); -static int pcnet32_rx(struct device *dev); -static void pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int pcnet32_close(struct device *dev); -static struct net_device_stats *pcnet32_get_stats(struct device *dev); -static void pcnet32_set_multicast_list(struct device *dev); +int pcnet32_probe(struct device *); +static int pcnet32_probe1(struct device *, unsigned long, unsigned char, int, int); +static int pcnet32_open(struct device *); +static int pcnet32_init_ring(struct device *); +static int pcnet32_start_xmit(struct sk_buff *, struct device *); +static int pcnet32_rx(struct device *); +static void pcnet32_interrupt(int, void *, struct pt_regs *); +static int pcnet32_close(struct device *); +static struct net_device_stats *pcnet32_get_stats(struct device *); +static void pcnet32_set_multicast_list(struct device *); +#ifdef HAVE_PRIVATE_IOCTL +static int pcnet32_mii_ioctl(struct device *, struct ifreq *, int); +#endif + +enum pci_flags_bit { + PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, + PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +}; + +struct pcnet32_pci_id_info { + const char *name; + u16 vendor_id, device_id, device_id_mask, flags; + int io_size; + int (*probe1) (struct device *, unsigned long, unsigned char, int, int); +}; + +static struct pcnet32_pci_id_info pcnet32_tbl[] = { + { "AMD PCnetPCI series", + 0x1022, 0x2000, 0xfffe, PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, + pcnet32_probe1}, + {0,} +}; + +static u16 pcnet32_wio_read_csr (unsigned long addr, int index) +{ + outw (index, addr+PCNET32_WIO_RAP); + return inw (addr+PCNET32_WIO_RDP); +} + +static void pcnet32_wio_write_csr (unsigned long addr, int index, u16 val) +{ + outw (index, addr+PCNET32_WIO_RAP); + outw (val, addr+PCNET32_WIO_RDP); +} + +static u16 pcnet32_wio_read_bcr (unsigned long addr, int index) +{ + outw (index, addr+PCNET32_WIO_RAP); + return inw (addr+PCNET32_WIO_BDP); +} + +static void pcnet32_wio_write_bcr (unsigned long addr, int index, u16 val) +{ + outw (index, addr+PCNET32_WIO_RAP); + outw (val, addr+PCNET32_WIO_BDP); +} + +static u16 pcnet32_wio_read_rap (unsigned long addr) +{ + return inw (addr+PCNET32_WIO_RAP); +} + +static void pcnet32_wio_write_rap (unsigned long addr, u16 val) +{ + outw (val, addr+PCNET32_WIO_RAP); +} + +static void pcnet32_wio_reset (unsigned long addr) +{ + inw (addr+PCNET32_WIO_RESET); +} + +static int pcnet32_wio_check (unsigned long addr) +{ + outw (88, addr+PCNET32_WIO_RAP); + return (inw (addr+PCNET32_WIO_RAP) == 88); +} + +static struct pcnet32_access pcnet32_wio = { + pcnet32_wio_read_csr, + pcnet32_wio_write_csr, + pcnet32_wio_read_bcr, + pcnet32_wio_write_bcr, + pcnet32_wio_read_rap, + pcnet32_wio_write_rap, + pcnet32_wio_reset +}; + +static u16 pcnet32_dwio_read_csr (unsigned long addr, int index) +{ + outl (index, addr+PCNET32_DWIO_RAP); + return (inl (addr+PCNET32_DWIO_RDP) & 0xffff); +} + +static void pcnet32_dwio_write_csr (unsigned long addr, int index, u16 val) +{ + outl (index, addr+PCNET32_DWIO_RAP); + outl (val, addr+PCNET32_DWIO_RDP); +} + +static u16 pcnet32_dwio_read_bcr (unsigned long addr, int index) +{ + outl (index, addr+PCNET32_DWIO_RAP); + return (inl (addr+PCNET32_DWIO_BDP) & 0xffff); +} + +static void pcnet32_dwio_write_bcr (unsigned long addr, int index, u16 val) +{ + outl (index, addr+PCNET32_DWIO_RAP); + outl (val, addr+PCNET32_DWIO_BDP); +} + +static u16 pcnet32_dwio_read_rap (unsigned long addr) +{ + return (inl (addr+PCNET32_DWIO_RAP) & 0xffff); +} + +static void pcnet32_dwio_write_rap (unsigned long addr, u16 val) +{ + outl (val, addr+PCNET32_DWIO_RAP); +} + +static void pcnet32_dwio_reset (unsigned long addr) +{ + inl (addr+PCNET32_DWIO_RESET); +} + +static int pcnet32_dwio_check (unsigned long addr) +{ + outl (88, addr+PCNET32_DWIO_RAP); + return (inl (addr+PCNET32_DWIO_RAP) == 88); +} + +static struct pcnet32_access pcnet32_dwio = { + pcnet32_dwio_read_csr, + pcnet32_dwio_write_csr, + pcnet32_dwio_read_bcr, + pcnet32_dwio_write_bcr, + pcnet32_dwio_read_rap, + pcnet32_dwio_write_rap, + pcnet32_dwio_reset + +}; -__initfunc(int pcnet32_probe (struct device *dev)) +int __init pcnet32_probe (struct device *dev) { - unsigned int ioaddr = dev ? dev->base_addr: 0; + unsigned long ioaddr = dev ? dev->base_addr: 0; unsigned int irq_line = dev ? dev->irq : 0; int *port; + int cards_found = 0; - if (ioaddr > 0x1ff) - return pcnet32_probe1(dev, ioaddr, irq_line, 0); - else if(ioaddr != 0) - return ENXIO; + +#ifndef __powerpc__ + if (ioaddr > 0x1ff) { + if (check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0) + return pcnet32_probe1(dev, ioaddr, irq_line, 0, 0); + else + return ENODEV; + } else +#endif + if(ioaddr != 0) + return ENXIO; #if defined(CONFIG_PCI) if (pci_present()) { - struct pci_dev *pdev = NULL; + struct pci_dev *pdev; + unsigned char pci_bus, pci_device_fn; + int pci_index; printk("pcnet32.c: PCI bios is present, checking for devices...\n"); - while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) { - unsigned short pci_command; + for (pci_index = 0; pci_index < 0xff; pci_index++) { + u16 vendor, device, pci_command; + int chip_idx; - irq_line = pdev->irq; + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, + pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) + break; + + pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); + + for (chip_idx = 0; pcnet32_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor == pcnet32_tbl[chip_idx].vendor_id && + (device & pcnet32_tbl[chip_idx].device_id_mask) == pcnet32_tbl[chip_idx].device_id) + break; + if (pcnet32_tbl[chip_idx].vendor_id == 0) + continue; + + pdev = pci_find_slot(pci_bus, pci_device_fn); ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; +#if defined(ADDR_64BITS) && defined(__alpha__) + ioaddr |= ((long)pdev->base_address[1]) << 32; +#endif + irq_line = pdev->irq; + + /* Avoid already found cards from previous pcnet32_probe() calls */ + if ((pcnet32_tbl[chip_idx].flags & PCI_USES_IO) && + check_region(ioaddr, pcnet32_tbl[chip_idx].io_size)) + continue; + /* PCI Spec 2.1 states that it is either the driver or PCI card's * responsibility to set the PCI Master Enable Bit if needed. * (From Mark Stockton ) */ pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - - /* Avoid already found cards from previous pcnet32_probe() calls */ - if (check_region(ioaddr, PCNET32_TOTAL_SIZE)) - continue; - if ( ! (pci_command & PCI_COMMAND_MASTER)) { printk("PCI Master Bit has not been set. Setting...\n"); pci_command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO; pci_write_config_word(pdev, PCI_COMMAND, pci_command); } + printk("Found PCnet/PCI at %#lx, irq %d.\n", ioaddr, irq_line); - printk("Found PCnet/PCI at %#x, irq %d.\n", - ioaddr, irq_line); - - if (pcnet32_probe1(dev, ioaddr, irq_line, 1) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "pcnet32.c: Probe of PCI card at %#x failed.\n", ioaddr); - break; + if (pcnet32_tbl[chip_idx].probe1(dev, ioaddr, irq_line, 1, cards_found) == 0) { + cards_found++; + dev = NULL; } - return 0; } } else #endif /* defined(CONFIG_PCI) */ /* now look for PCnet32 VLB cards */ for (port = pcnet32_portlist; *port; port++) { - unsigned int ioaddr = *port; + unsigned long ioaddr = *port; if ( check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0) { /* check if there is really a pcnet chip on that ioaddr */ if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57) && - (pcnet32_probe1(dev, ioaddr, 0, 0) == 0)) - return 0; + (pcnet32_probe1(dev, ioaddr, 0, 0, 0) == 0)) + cards_found++; } } - return ENODEV; + return cards_found ? 0: ENODEV; } /* pcnet32_probe1 */ -__initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared)) +static int __init +pcnet32_probe1(struct device *dev, unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx) { struct pcnet32_private *lp; - int i,full_duplex = 0; + int i,media,fdx = 0, mii = 0; + int chip_version; char *chipname; + char *priv; + struct pcnet32_access *a; - inw(ioaddr+PCNET32_RESET); /* Reset the PCNET32 */ + /* reset the chip */ + pcnet32_dwio_reset(ioaddr); + pcnet32_wio_reset(ioaddr); + + if (pcnet32_wio_read_csr (ioaddr, 0) == 4 && pcnet32_wio_check (ioaddr)) { + a = &pcnet32_wio; + } else { + if (pcnet32_dwio_read_csr (ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { + a = &pcnet32_dwio; + } else + return ENODEV; + } - outw(0x0000, ioaddr+PCNET32_ADDR); /* Switch to window 0 */ - if (inw(ioaddr+PCNET32_DATA) != 0x0004) - return ENODEV; - - /* Get the version of the chip. */ - outw(88, ioaddr+PCNET32_ADDR); - if (inw(ioaddr+PCNET32_ADDR) != 88) { - /* should never happen */ + chip_version = a->read_csr (ioaddr, 88) | (a->read_csr (ioaddr,89) << 16); + if (pcnet32_debug > 2) + printk(" PCnet chip version is %#x.\n", chip_version); + if ((chip_version & 0xfff) != 0x003) return ENODEV; - } else { /* Good, it's a newer chip. */ - int chip_version = inw(ioaddr+PCNET32_DATA); - outw(89, ioaddr+PCNET32_ADDR); - chip_version |= inw(ioaddr+PCNET32_DATA) << 16; + chip_version = (chip_version >> 12) & 0xffff; + switch (chip_version) { + case 0x2420: + chipname = "PCnet/PCI 79C970"; + break; + case 0x2430: + if (shared) + chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */ + else + chipname = "PCnet/32 79C965"; + break; + case 0x2621: + chipname = "PCnet/PCI II 79C970A"; + fdx = 1; + break; + case 0x2623: + chipname = "PCnet/FAST 79C971"; + fdx = 1; mii = 1; + break; + case 0x2624: + chipname = "PCnet/FAST+ 79C972"; + fdx = 1; mii = 1; + break; + case 0x2626: + chipname = "PCnet/Home 79C978"; + fdx = 1; + /* + * This is based on specs published at www.amd.com. This section + * assumes that a card with a 79C978 wants to go into 1Mb HomePNA + * mode. The 79C978 can also go into standard ethernet, and there + * probably should be some sort of module option to select the + * mode by which the card should operate + */ + /* switch to home wiring mode */ + media = a->read_bcr (ioaddr, 49); if (pcnet32_debug > 2) - printk(" PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) - return ENODEV; - chip_version = (chip_version >> 12) & 0xffff; - switch (chip_version) { - case 0x2420: - chipname = "PCnet/PCI 79C970"; - break; - case 0x2430: - if (shared) - chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */ - else - chipname = "PCnet/32 79C965"; - break; - case 0x2621: - chipname = "PCnet/PCI II 79C970A"; - full_duplex = 1; - break; - case 0x2623: - chipname = "PCnet/FAST 79C971"; - full_duplex = 1; - break; - case 0x2624: - chipname = "PCnet/FAST+ 79C972"; - full_duplex = 1; - break; - default: - printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version); - return ENODEV; - } + printk("pcnet32: pcnet32 media value %#x.\n", media); + media &= ~3; + media |= 1; + if (pcnet32_debug > 2) + printk("pcnet32: pcnet32 media reset to %#x.\n", media); + a->write_bcr (ioaddr, 49, media); + break; + default: + printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version); + return ENODEV; } - if (dev == NULL) - dev = init_etherdev(0, 0); + dev = init_etherdev(dev, 0); - printk("%s: %s at %#3x,", dev->name, chipname, ioaddr); + printk(KERN_INFO "%s: %s at %#3lx,", dev->name, chipname, ioaddr); /* There is a 16 byte station address PROM at the base address. The first six bytes are the station address. */ @@ -345,15 +578,31 @@ dev->base_addr = ioaddr; request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname); - /* Make certain the data structures used by the PCnet32 are 16byte aligned and DMAble. */ - lp = (struct pcnet32_private *) (((unsigned long)kmalloc(sizeof(*lp)+15, GFP_DMA | GFP_KERNEL)+15) & ~15); + if ((priv = kmalloc(sizeof(*lp)+15,GFP_KERNEL)) == NULL) + return ENOMEM; + + /* + * Make certain the data structures used by + * the PCnet32 are 16byte aligned + */ + lp = (struct pcnet32_private *)(((unsigned long)priv+15) & ~15); memset(lp, 0, sizeof(*lp)); dev->priv = lp; lp->name = chipname; lp->shared_irq = shared; - lp->full_duplex = full_duplex; - lp->options = options; + lp->full_duplex = fdx; + lp->mii = mii; + if (options[card_idx] > sizeof (options_mapping)) + lp->options = PORT_ASEL; + else + lp->options = options_mapping[options[card_idx]]; + + if (fdx && !(lp->options & PORT_ASEL) && full_duplex[card_idx]) + lp->options |= PORT_FD; + + lp->origmem = priv; + lp->a = *a; /* detect special T1/E1 WAN card by checking for MAC address */ if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75) @@ -369,24 +618,17 @@ lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring)); /* switch pcnet32 to 32bit mode */ - outw(0x0014, ioaddr+PCNET32_ADDR); - outw(0x0002, ioaddr+PCNET32_BUS_IF); + a->write_bcr (ioaddr, 20, 2); - outw(0x0001, ioaddr+PCNET32_ADDR); - inw(ioaddr+PCNET32_ADDR); - outw(virt_to_bus(&lp->init_block) & 0xffff, ioaddr+PCNET32_DATA); - outw(0x0002, ioaddr+PCNET32_ADDR); - inw(ioaddr+PCNET32_ADDR); - outw(virt_to_bus(&lp->init_block) >> 16, ioaddr+PCNET32_DATA); - outw(0x0000, ioaddr+PCNET32_ADDR); - inw(ioaddr+PCNET32_ADDR); + a->write_csr (ioaddr, 1, virt_to_bus(&lp->init_block) & 0xffff); + a->write_csr (ioaddr, 2, virt_to_bus(&lp->init_block) >> 16); if (irq_line) { dev->irq = irq_line; } if (dev->irq >= 2) - printk(" assigned IRQ %d.\n", dev->irq); + printk(" assigned IRQ %d.\n", dev->irq); else { unsigned long irq_mask = probe_irq_on(); @@ -396,7 +638,7 @@ * boards will work. */ /* Trigger an initialization just for the interrupt. */ - outw(0x0041, ioaddr+PCNET32_DATA); + a->write_csr (ioaddr, 0, 0x41); mdelay (1); dev->irq = probe_irq_off (irq_mask); @@ -409,7 +651,7 @@ } if (pcnet32_debug > 0) - printk(version); + printk(version); /* The PCNET32-specific entries in the device structure. */ dev->open = &pcnet32_open; @@ -417,6 +659,10 @@ dev->stop = &pcnet32_close; dev->get_stats = &pcnet32_get_stats; dev->set_multicast_list = &pcnet32_set_multicast_list; +#ifdef HAVE_PRIVATE_IOCTL + dev->do_ioctl = &pcnet32_mii_ioctl; +#endif + #ifdef MODULE lp->next = pcnet32_dev; @@ -432,95 +678,96 @@ static int pcnet32_open(struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - unsigned int ioaddr = dev->base_addr; - unsigned short val; - int i; - - if (dev->irq == 0 || - request_irq(dev->irq, &pcnet32_interrupt, - lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) { - return -EAGAIN; - } + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 val; + int i; + + if (dev->irq == 0 || + request_irq(dev->irq, &pcnet32_interrupt, + lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) { + return -EAGAIN; + } - /* Reset the PCNET32 */ - inw(ioaddr+PCNET32_RESET); + /* Reset the PCNET32 */ + lp->a.reset (ioaddr); - /* switch pcnet32 to 32bit mode */ - outw(0x0014, ioaddr+PCNET32_ADDR); - outw(0x0002, ioaddr+PCNET32_BUS_IF); - - if (pcnet32_debug > 1) - printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", - dev->name, dev->irq, - (u32) virt_to_bus(lp->tx_ring), - (u32) virt_to_bus(lp->rx_ring), - (u32) virt_to_bus(&lp->init_block)); - - /* set/reset autoselect bit */ - outw(0x0002, ioaddr+PCNET32_ADDR); - val = inw(ioaddr+PCNET32_BUS_IF) & ~2; - if (lp->options & PORT_ASEL) - val |= 2; - outw(val, ioaddr+PCNET32_BUS_IF); - - /* handle full duplex setting */ - if (lp->full_duplex) { - outw (0x0009, ioaddr+PCNET32_ADDR); - val = inw(ioaddr+PCNET32_BUS_IF) & ~3; - if (lp->options & PORT_FD) { - val |= 1; - if (lp->options == (PORT_FD | PORT_AUI)) - val |= 2; - } - outw(val, ioaddr+PCNET32_BUS_IF); + /* switch pcnet32 to 32bit mode */ + lp->a.write_csr (ioaddr, 20, 2); + + if (pcnet32_debug > 1) + printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", + dev->name, dev->irq, + (u32) virt_to_bus(lp->tx_ring), + (u32) virt_to_bus(lp->rx_ring), + (u32) virt_to_bus(&lp->init_block)); + + /* set/reset autoselect bit */ + val = lp->a.read_bcr (ioaddr, 2) & ~2; + if (lp->options & PORT_ASEL) + val |= 2; + lp->a.write_bcr (ioaddr, 2, val); + + /* handle full duplex setting */ + if (lp->full_duplex) { + val = lp->a.read_bcr (ioaddr, 9) & ~3; + if (lp->options & PORT_FD) { + val |= 1; + if (lp->options == (PORT_FD | PORT_AUI)) + val |= 2; } + lp->a.write_bcr (ioaddr, 9, val); + } - /* set/reset GPSI bit in test register */ - outw (0x007c, ioaddr+PCNET32_ADDR); - val = inw(ioaddr+PCNET32_DATA) & ~0x10; - if ((lp->options & PORT_PORTSEL) == PORT_GPSI) - val |= 0x10; - outw(val, ioaddr+PCNET32_DATA); - - lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7); - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - if (pcnet32_init_ring(dev)) - return -ENOMEM; - - /* Re-initialize the PCNET32, and start it when done. */ - outw(0x0001, ioaddr+PCNET32_ADDR); - outw(virt_to_bus(&lp->init_block) &0xffff, ioaddr+PCNET32_DATA); - outw(0x0002, ioaddr+PCNET32_ADDR); - outw(virt_to_bus(&lp->init_block) >> 16, ioaddr+PCNET32_DATA); - - outw(0x0004, ioaddr+PCNET32_ADDR); - outw(0x0915, ioaddr+PCNET32_DATA); - - outw(0x0000, ioaddr+PCNET32_ADDR); - outw(0x0001, ioaddr+PCNET32_DATA); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - i = 0; - while (i++ < 100) - if (inw(ioaddr+PCNET32_DATA) & 0x0100) - break; - /* - * We used to clear the InitDone bit, 0x0100, here but Mark Stockton - * reports that doing so triggers a bug in the '974. - */ - outw(0x0042, ioaddr+PCNET32_DATA); - - if (pcnet32_debug > 2) - printk("%s: PCNET32 open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, (u32) virt_to_bus(&lp->init_block), inw(ioaddr+PCNET32_DATA)); + /* set/reset GPSI bit in test register */ + val = lp->a.read_csr (ioaddr, 124) & ~0x10; + if ((lp->options & PORT_PORTSEL) == PORT_GPSI) + val |= 0x10; + lp->a.write_csr (ioaddr, 124, val); + + if (lp->mii & (lp->options & PORT_ASEL)) { + val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */ + if (lp->options & PORT_FD) + val |= 0x10; + if (lp->options & PORT_100) + val |= 0x08; + lp->a.write_bcr (ioaddr, 32, val); + } + + lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7); + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + if (pcnet32_init_ring(dev)) + return -ENOMEM; + + /* Re-initialize the PCNET32, and start it when done. */ + lp->a.write_csr (ioaddr, 1, virt_to_bus(&lp->init_block) &0xffff); + lp->a.write_csr (ioaddr, 2, virt_to_bus(&lp->init_block) >> 16); + + lp->a.write_csr (ioaddr, 4, 0x0915); + lp->a.write_csr (ioaddr, 0, 0x0001); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + i = 0; + while (i++ < 100) + if (lp->a.read_csr (ioaddr, 0) & 0x0100) + break; + /* + * We used to clear the InitDone bit, 0x0100, here but Mark Stockton + * reports that doing so triggers a bug in the '974. + */ + lp->a.write_csr (ioaddr, 0, 0x0042); + + if (pcnet32_debug > 2) + printk("%s: PCNET32 open after %d ticks, init block %#x csr0 %4.4x.\n", + dev->name, i, (u32) virt_to_bus(&lp->init_block), + lp->a.read_csr (ioaddr, 0)); - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - return 0; /* Always succeed */ + return 0; /* Always succeed */ } /* @@ -539,15 +786,15 @@ static void pcnet32_purge_tx_ring(struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - int i; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + int i; - for (i = 0; i < TX_RING_SIZE; i++) { - if (lp->tx_skbuff[i]) { - dev_kfree_skb(lp->tx_skbuff[i]); - lp->tx_skbuff[i] = NULL; - } + for (i = 0; i < TX_RING_SIZE; i++) { + if (lp->tx_skbuff[i]) { + dev_kfree_skb(lp->tx_skbuff[i]); + lp->tx_skbuff[i] = NULL; } + } } @@ -555,445 +802,437 @@ static int pcnet32_init_ring(struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - int i; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + int i; - lp->tx_full = 0; - lp->cur_rx = lp->cur_tx = 0; - lp->dirty_rx = lp->dirty_tx = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - if (lp->rx_skbuff[i] == NULL) { - if (!(lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { - /* there is not much, we can do at this point */ - printk ("%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); - return -1; - } - skb_reserve (lp->rx_skbuff[i], 2); + lp->tx_full = 0; + lp->cur_rx = lp->cur_tx = 0; + lp->dirty_rx = lp->dirty_tx = 0; + + for (i = 0; i < RX_RING_SIZE; i++) { + if (lp->rx_skbuff[i] == NULL) { + if (!(lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { + /* there is not much, we can do at this point */ + printk ("%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); + return -1; } - lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(lp->rx_skbuff[i]->tail)); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[i].status = le16_to_cpu(0x8000); - } - /* The Tx buffer address is filled in as needed, but we do need to clear - the upper ownership bit. */ - for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_ring[i].base = 0; - lp->tx_ring[i].status = 0; + skb_reserve (lp->rx_skbuff[i], 2); } + lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(lp->rx_skbuff[i]->tail)); + lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[i].status = le16_to_cpu(0x8000); + } + /* The Tx buffer address is filled in as needed, but we do need to clear + the upper ownership bit. */ + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].base = 0; + lp->tx_ring[i].status = 0; + } - lp->init_block.tlen_rlen = TX_RING_LEN_BITS | RX_RING_LEN_BITS; - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring)); - lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring)); - return 0; + lp->init_block.tlen_rlen = TX_RING_LEN_BITS | RX_RING_LEN_BITS; + for (i = 0; i < 6; i++) + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring)); + lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring)); + return 0; } static void pcnet32_restart(struct device *dev, unsigned int csr0_bits) { - int i; - unsigned int ioaddr = dev->base_addr; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned long ioaddr = dev->base_addr; + int i; - pcnet32_purge_tx_ring(dev); - if (pcnet32_init_ring(dev)) - return; - - outw(0x0000, ioaddr + PCNET32_ADDR); - /* ReInit Ring */ - outw(0x0001, ioaddr + PCNET32_DATA); - i = 0; - while (i++ < 100) - if (inw(ioaddr+PCNET32_DATA) & 0x0100) - break; + pcnet32_purge_tx_ring(dev); + if (pcnet32_init_ring(dev)) + return; + + /* ReInit Ring */ + lp->a.write_csr (ioaddr, 0, 1); + i = 0; + while (i++ < 100) + if (lp->a.read_csr (ioaddr, 0) & 0x0100) + break; - outw(csr0_bits, ioaddr + PCNET32_DATA); + lp->a.write_csr (ioaddr, 0, csr0_bits); } static int pcnet32_start_xmit(struct sk_buff *skb, struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - unsigned int ioaddr = dev->base_addr; - int entry; - unsigned long flags; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < HZ/2) - return 1; - outw(0, ioaddr+PCNET32_ADDR); - printk("%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, inw(ioaddr+PCNET32_DATA)); - outw(0x0004, ioaddr+PCNET32_DATA); - lp->stats.tx_errors++; - if (pcnet32_debug > 2) { - int i; - printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", - lp->cur_rx); - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, - lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->tx_ring[i].base, -lp->tx_ring[i].length, - lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); - printk("\n"); - } - pcnet32_restart(dev, 0x0042); - - dev->tbusy = 0; - dev->trans_start = jiffies; - dev_kfree_skb(skb); - return 0; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned int ioaddr = dev->base_addr; + int entry; + unsigned long flags; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < HZ/2) + return 1; + printk("%s: transmit timed out, status %4.4x, resetting.\n", + dev->name, lp->a.read_csr (ioaddr, 0)); + lp->a.write_csr (ioaddr, 0, 0x0004); + lp->stats.tx_errors++; + if (pcnet32_debug > 2) { + int i; + printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", + lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", + lp->cur_rx); + for (i = 0 ; i < RX_RING_SIZE; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, + lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); + for (i = 0 ; i < TX_RING_SIZE; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + lp->tx_ring[i].base, -lp->tx_ring[i].length, + lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); + printk("\n"); } + pcnet32_restart(dev, 0x0042); - if (pcnet32_debug > 3) { - outw(0x0000, ioaddr+PCNET32_ADDR); - printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name, - inw(ioaddr+PCNET32_DATA)); - } + dev->tbusy = 0; + dev->trans_start = jiffies; + dev_kfree_skb(skb); + return 0; + } - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } + if (pcnet32_debug > 3) { + printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", + dev->name, lp->a.read_csr (ioaddr, 0)); + } - save_flags (flags); - cli (); + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } - /* Fill in a Tx ring entry */ + save_flags (flags); + cli (); - /* Mask to ring buffer boundary. */ - entry = lp->cur_tx & TX_RING_MOD_MASK; + /* Fill in a Tx ring entry */ - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ + /* Mask to ring buffer boundary. */ + entry = lp->cur_tx & TX_RING_MOD_MASK; - lp->tx_ring[entry].length = le16_to_cpu(-skb->len); + /* Caution: the write order is important here, set the base address + with the "ownership" bits last. */ - lp->tx_ring[entry].misc = 0x00000000; + lp->tx_ring[entry].length = le16_to_cpu(-skb->len); - lp->tx_skbuff[entry] = skb; - lp->tx_ring[entry].base = (u32)le32_to_cpu(virt_to_bus(skb->data)); - lp->tx_ring[entry].status = le16_to_cpu(0x8300); + lp->tx_ring[entry].misc = 0x00000000; - lp->cur_tx++; - lp->stats.tx_bytes += skb->len; + lp->tx_skbuff[entry] = skb; + lp->tx_ring[entry].base = (u32)le32_to_cpu(virt_to_bus(skb->data)); + lp->tx_ring[entry].status = le16_to_cpu(0x8300); - /* Trigger an immediate send poll. */ - outw(0x0000, ioaddr+PCNET32_ADDR); - outw(0x0048, ioaddr+PCNET32_DATA); + lp->cur_tx++; + lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; + /* Trigger an immediate send poll. */ + lp->a.write_csr (ioaddr, 0, 0x0048); - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - clear_bit (0, (void *)&dev->tbusy); - else - lp->tx_full = 1; - restore_flags(flags); - return 0; + dev->trans_start = jiffies; + + if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) + clear_bit (0, (void *)&dev->tbusy); + else + lp->tx_full = 1; + restore_flags(flags); + return 0; } /* The PCNET32 interrupt handler. */ static void pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - struct device *dev = (struct device *)dev_id; - struct pcnet32_private *lp; - unsigned int csr0, ioaddr; - int boguscnt = max_interrupt_work; - int must_restart; - - if (dev == NULL) { - printk ("pcnet32_interrupt(): irq %d for unknown device.\n", irq); - return; - } + struct device *dev = (struct device *)dev_id; + struct pcnet32_private *lp; + unsigned long ioaddr; + u16 csr0; + int boguscnt = max_interrupt_work; + int must_restart; - ioaddr = dev->base_addr; - lp = (struct pcnet32_private *)dev->priv; - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); + if (dev == NULL) { + printk ("pcnet32_interrupt(): irq %d for unknown device.\n", irq); + return; + } - dev->interrupt = 1; + ioaddr = dev->base_addr; + lp = (struct pcnet32_private *)dev->priv; + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); - outw(0x00, dev->base_addr + PCNET32_ADDR); - while ((csr0 = inw(dev->base_addr + PCNET32_DATA)) & 0x8600 && --boguscnt >= 0) { - /* Acknowledge all of the current interrupt sources ASAP. */ - outw(csr0 & ~0x004f, dev->base_addr + PCNET32_DATA); + dev->interrupt = 1; - must_restart = 0; + while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { + /* Acknowledge all of the current interrupt sources ASAP. */ + lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); - if (pcnet32_debug > 5) - printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, inw(dev->base_addr + PCNET32_DATA)); + must_restart = 0; - if (csr0 & 0x0400) /* Rx interrupt */ - pcnet32_rx(dev); + if (pcnet32_debug > 5) + printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", + dev->name, csr0, lp->a.read_csr (ioaddr, 0)); - if (csr0 & 0x0200) { /* Tx-done interrupt */ - int dirty_tx = lp->dirty_tx; + if (csr0 & 0x0400) /* Rx interrupt */ + pcnet32_rx(dev); - while (dirty_tx < lp->cur_tx) { - int entry = dirty_tx & TX_RING_MOD_MASK; - int status = (short)le16_to_cpu(lp->tx_ring[entry].status); + if (csr0 & 0x0200) { /* Tx-done interrupt */ + int dirty_tx = lp->dirty_tx; + + while (dirty_tx < lp->cur_tx) { + int entry = dirty_tx & TX_RING_MOD_MASK; + int status = (short)le16_to_cpu(lp->tx_ring[entry].status); - if (status < 0) - break; /* It still hasn't been Txed */ + if (status < 0) + break; /* It still hasn't been Txed */ - lp->tx_ring[entry].base = 0; + lp->tx_ring[entry].base = 0; - if (status & 0x4000) { - /* There was an major error, log it. */ - int err_status = le32_to_cpu(lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (err_status & 0x04000000) lp->stats.tx_aborted_errors++; - if (err_status & 0x08000000) lp->stats.tx_carrier_errors++; - if (err_status & 0x10000000) lp->stats.tx_window_errors++; - if (err_status & 0x40000000) { - /* Ackk! On FIFO errors the Tx unit is turned off! */ - lp->stats.tx_fifo_errors++; - /* Remove this verbosity later! */ - printk("%s: Tx FIFO error! Status %4.4x.\n", - dev->name, csr0); - must_restart = 1; + if (status & 0x4000) { + /* There was an major error, log it. */ + int err_status = le32_to_cpu(lp->tx_ring[entry].misc); + lp->stats.tx_errors++; + if (err_status & 0x04000000) lp->stats.tx_aborted_errors++; + if (err_status & 0x08000000) lp->stats.tx_carrier_errors++; + if (err_status & 0x10000000) lp->stats.tx_window_errors++; + if (err_status & 0x40000000) { + /* Ackk! On FIFO errors the Tx unit is turned off! */ + lp->stats.tx_fifo_errors++; + /* Remove this verbosity later! */ + printk("%s: Tx FIFO error! Status %4.4x.\n", + dev->name, csr0); + must_restart = 1; } - } else { - if (status & 0x1800) - lp->stats.collisions++; - lp->stats.tx_packets++; - } - - /* We must free the original skb */ - if (lp->tx_skbuff[entry]) { - dev_kfree_skb(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; - } - dirty_tx++; - } + } else { + if (status & 0x1800) + lp->stats.collisions++; + lp->stats.tx_packets++; + } + + /* We must free the original skb */ + if (lp->tx_skbuff[entry]) { + dev_kfree_skb(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = 0; + } + dirty_tx++; + } #ifndef final_version - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dirty_tx, lp->cur_tx, lp->tx_full); - dirty_tx += TX_RING_SIZE; - } + if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dirty_tx, lp->cur_tx, lp->tx_full); + dirty_tx += TX_RING_SIZE; + } #endif + if (lp->tx_full && dev->tbusy + && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + clear_bit(0, (void *)&dev->tbusy); + mark_bh(NET_BH); + } + lp->dirty_tx = dirty_tx; + } - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - clear_bit(0, (void *)&dev->tbusy); - mark_bh(NET_BH); - } - lp->dirty_tx = dirty_tx; - } - - /* Log misc errors. */ - if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */ - if (csr0 & 0x1000) { - /* - * this happens when our receive ring is full. This shouldn't - * be a problem as we will see normal rx interrupts for the frames - * in the receive ring. But there are some PCI chipsets (I can reproduce - * this on SP3G with Intel saturn chipset) which have sometimes problems - * and will fill up the receive ring with error descriptors. In this - * situation we don't get a rx interrupt, but a missed frame interrupt sooner - * or later. So we try to clean up our receive ring here. - */ - pcnet32_rx(dev); - lp->stats.rx_errors++; /* Missed a Rx frame. */ - } - if (csr0 & 0x0800) { - printk("%s: Bus master arbitration failure, status %4.4x.\n", - dev->name, csr0); - /* unlike for the lance, there is no restart needed */ - } + /* Log misc errors. */ + if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */ + if (csr0 & 0x1000) { + /* + * this happens when our receive ring is full. This shouldn't + * be a problem as we will see normal rx interrupts for the frames + * in the receive ring. But there are some PCI chipsets (I can reproduce + * this on SP3G with Intel saturn chipset) which have sometimes problems + * and will fill up the receive ring with error descriptors. In this + * situation we don't get a rx interrupt, but a missed frame interrupt sooner + * or later. So we try to clean up our receive ring here. + */ + pcnet32_rx(dev); + lp->stats.rx_errors++; /* Missed a Rx frame. */ + } + if (csr0 & 0x0800) { + printk("%s: Bus master arbitration failure, status %4.4x.\n", + dev->name, csr0); + /* unlike for the lance, there is no restart needed */ + } - if (must_restart) { - /* stop the chip to clear the error condition, then restart */ - outw(0x0000, dev->base_addr + PCNET32_ADDR); - outw(0x0004, dev->base_addr + PCNET32_DATA); - pcnet32_restart(dev, 0x0002); - } + if (must_restart) { + /* stop the chip to clear the error condition, then restart */ + lp->a.write_csr (ioaddr, 0, 0x0004); + pcnet32_restart(dev, 0x0002); } + } /* Clear any other interrupt, and set interrupt enable. */ - outw(0x0000, dev->base_addr + PCNET32_ADDR); - outw(0x7940, dev->base_addr + PCNET32_DATA); + lp->a.write_csr (ioaddr, 0, 0x7940); - if (pcnet32_debug > 4) - printk("%s: exiting interrupt, csr%d=%#4.4x.\n", - dev->name, inw(ioaddr + PCNET32_ADDR), - inw(dev->base_addr + PCNET32_DATA)); + if (pcnet32_debug > 4) + printk("%s: exiting interrupt, csr0=%#4.4x.\n", + dev->name, lp->a.read_csr (ioaddr, 0)); - dev->interrupt = 0; - return; + dev->interrupt = 0; + return; } static int pcnet32_rx(struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - int entry = lp->cur_rx & RX_RING_MOD_MASK; - int i; - - /* If we own the next entry, it's a new packet. Send it up. */ - while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { - int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; - - if (status != 0x03) { /* There was an error. */ - /* There is a tricky error noted by John Murphy, - to Russ Nelson: Even with full-sized - buffers it's possible for a jabber packet to use two - buffers, with only the last correctly noting the error. */ - if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x20) lp->stats.rx_frame_errors++; - if (status & 0x10) lp->stats.rx_over_errors++; - if (status & 0x08) lp->stats.rx_crc_errors++; - if (status & 0x04) lp->stats.rx_fifo_errors++; - lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); - } - else - { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; - struct sk_buff *skb; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + int entry = lp->cur_rx & RX_RING_MOD_MASK; + int i; + + /* If we own the next entry, it's a new packet. Send it up. */ + while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { + int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; + + if (status != 0x03) { /* There was an error. */ + /* + * There is a tricky error noted by John Murphy, + * to Russ Nelson: Even with full-sized + * buffers it's possible for a jabber packet to use two + * buffers, with only the last correctly noting the error. + */ + if (status & 0x01) /* Only count a general error at the */ + lp->stats.rx_errors++; /* end of a packet.*/ + if (status & 0x20) lp->stats.rx_frame_errors++; + if (status & 0x10) lp->stats.rx_over_errors++; + if (status & 0x08) lp->stats.rx_crc_errors++; + if (status & 0x04) lp->stats.rx_fifo_errors++; + lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); + } else { + /* Malloc up new buffer, compatible with net-2e. */ + short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; + struct sk_buff *skb; - if(pkt_len < 60) { - printk("%s: Runt packet!\n",dev->name); - lp->stats.rx_errors++; - } else { - int rx_in_place = 0; + if(pkt_len < 60) { + printk("%s: Runt packet!\n",dev->name); + lp->stats.rx_errors++; + } else { + int rx_in_place = 0; - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; - if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) { - skb_reserve (newskb, 2); - skb = lp->rx_skbuff[entry]; - skb_put (skb, pkt_len); - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; - lp->rx_ring[entry].base = le32_to_cpu(virt_to_bus(newskb->tail)); - rx_in_place = 1; - } else - skb = NULL; - } else - skb = dev_alloc_skb(pkt_len+2); + if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) { + skb_reserve (newskb, 2); + skb = lp->rx_skbuff[entry]; + skb_put (skb, pkt_len); + lp->rx_skbuff[entry] = newskb; + newskb->dev = dev; + lp->rx_ring[entry].base = le32_to_cpu(virt_to_bus(newskb->tail)); + rx_in_place = 1; + } else + skb = NULL; + } else + skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - for (i=0; i < RX_RING_SIZE; i++) - if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0) - break; - - if (i > RX_RING_SIZE -2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - lp->cur_rx++; - } - break; - } - skb->dev = dev; - if (!rx_in_place) { - skb_reserve(skb,2); /* 16 byte align */ - skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)bus_to_virt(le32_to_cpu(lp->rx_ring[entry].base)), - pkt_len,0); - } - lp->stats.rx_bytes += skb->len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } + if (skb == NULL) { + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + for (i=0; i < RX_RING_SIZE; i++) + if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0) + break; + + if (i > RX_RING_SIZE -2) { + lp->stats.rx_dropped++; + lp->rx_ring[entry].status |= le16_to_cpu(0x8000); + lp->cur_rx++; + } + break; } - /* The docs say that the buffer length isn't touched, but Andrew Boyd - of QNX reports that some revs of the 79C965 clear it. */ - lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - entry = (++lp->cur_rx) & RX_RING_MOD_MASK; + skb->dev = dev; + if (!rx_in_place) { + skb_reserve(skb,2); /* 16 byte align */ + skb_put(skb,pkt_len); /* Make room */ + eth_copy_and_sum(skb, + (unsigned char *)bus_to_virt(le32_to_cpu(lp->rx_ring[entry].base)), + pkt_len,0); + } + lp->stats.rx_bytes += skb->len; + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + lp->stats.rx_packets++; + } } + /* + * The docs say that the buffer length isn't touched, but Andrew Boyd + * of QNX reports that some revs of the 79C965 clear it. + */ + lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[entry].status |= le16_to_cpu(0x8000); + entry = (++lp->cur_rx) & RX_RING_MOD_MASK; + } - /* We should check that at least two ring entries are free. If not, - we should free one and mark stats->rx_dropped++. */ - - return 0; + return 0; } static int pcnet32_close(struct device *dev) { - unsigned int ioaddr = dev->base_addr; - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - int i; - - dev->start = 0; - set_bit (0, (void *)&dev->tbusy); - - outw(112, ioaddr+PCNET32_ADDR); - lp->stats.rx_missed_errors = inw(ioaddr+PCNET32_DATA); - - outw(0, ioaddr+PCNET32_ADDR); - - if (pcnet32_debug > 1) - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(ioaddr+PCNET32_DATA)); - - /* We stop the PCNET32 here -- it occasionally polls - memory if we don't. */ - outw(0x0004, ioaddr+PCNET32_DATA); - - free_irq(dev->irq, dev); - - /* free all allocated skbuffs */ - for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_ring[i].status = 0; - if (lp->rx_skbuff[i]) - dev_kfree_skb(lp->rx_skbuff[i]); - lp->rx_skbuff[i] = NULL; - } + unsigned long ioaddr = dev->base_addr; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + int i; + + dev->start = 0; + set_bit (0, (void *)&dev->tbusy); + + lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); + + if (pcnet32_debug > 1) + printk("%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, lp->a.read_csr (ioaddr, 0)); + + /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ + lp->a.write_csr (ioaddr, 0, 0x0004); + + /* + * Switch back to 16bit mode to avoid problems with dumb + * DOS packet driver after a warm reboot + */ + lp->a.write_bcr (ioaddr, 20, 4); + + free_irq(dev->irq, dev); + + /* free all allocated skbuffs */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].status = 0; + if (lp->rx_skbuff[i]) + dev_kfree_skb(lp->rx_skbuff[i]); + lp->rx_skbuff[i] = NULL; + } - for (i = 0; i < TX_RING_SIZE; i++) { - if (lp->tx_skbuff[i]) - dev_kfree_skb(lp->tx_skbuff[i]); - lp->rx_skbuff[i] = NULL; - } + for (i = 0; i < TX_RING_SIZE; i++) { + if (lp->tx_skbuff[i]) + dev_kfree_skb(lp->tx_skbuff[i]); + lp->rx_skbuff[i] = NULL; + } - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; - return 0; + return 0; } static struct net_device_stats * pcnet32_get_stats(struct device *dev) { - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - unsigned int ioaddr = dev->base_addr; - unsigned short saved_addr; - unsigned long flags; - - save_flags(flags); - cli(); - saved_addr = inw(ioaddr+PCNET32_ADDR); - outw(112, ioaddr+PCNET32_ADDR); - lp->stats.rx_missed_errors = inw(ioaddr+PCNET32_DATA); - outw(saved_addr, ioaddr+PCNET32_ADDR); - restore_flags(flags); + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 saved_addr; + unsigned long flags; + + save_flags(flags); + cli(); + saved_addr = lp->a.read_rap(ioaddr); + lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); + lp->a.write_rap(ioaddr, saved_addr); + restore_flags(flags); - return &lp->stats; + return &lp->stats; } - /* taken from the sunlance driver, which it took from the depca driver */ static void pcnet32_load_multicast (struct device *dev) { @@ -1044,34 +1283,68 @@ } -/* Set or clear the multicast filter for this adaptor. +/* + * Set or clear the multicast filter for this adaptor. */ - static void pcnet32_set_multicast_list(struct device *dev) { - unsigned int ioaddr = dev->base_addr; - struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned long ioaddr = dev->base_addr; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; - if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); - lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7); - } else { - lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7); - pcnet32_load_multicast (dev); - } + if (dev->flags&IFF_PROMISC) { + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7); + } else { + lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7); + pcnet32_load_multicast (dev); + } - outw(0, ioaddr+PCNET32_ADDR); - outw(0x0004, ioaddr+PCNET32_DATA); /* Temporarily stop the lance. */ + lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ - pcnet32_restart(dev, 0x0042); /* Resume normal operation */ + pcnet32_restart(dev, 0x0042); /* Resume normal operation */ } +#ifdef HAVE_PRIVATE_IOCTL +static int pcnet32_mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) +{ + unsigned long ioaddr = dev->base_addr; + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + u16 *data = (u16 *)&rq->ifr_data; + int phyaddr = lp->a.read_bcr (ioaddr, 33); + + if (lp->mii) { + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = (phyaddr >> 5) & 0x1f; + /* Fall Through */ + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + lp->a.write_bcr (ioaddr, 33, ((data[0] & 0x1f) << 5) | (data[1] & 0x1f)); + data[3] = lp->a.read_bcr (ioaddr, 34); + lp->a.write_bcr (ioaddr, 33, phyaddr); + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + if (!suser()) + return -EPERM; + lp->a.write_bcr (ioaddr, 33, ((data[0] & 0x1f) << 5) | (data[1] & 0x1f)); + lp->a.write_bcr (ioaddr, 34, data[2]); + lp->a.write_bcr (ioaddr, 33, phyaddr); + return 0; + default: + return -EOPNOTSUPP; + } + } + return -EOPNOTSUPP; +} +#endif /* HAVE_PRIVATE_IOCTL */ + #ifdef MODULE MODULE_PARM(debug, "i"); -MODULE_PARM(options, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); + /* An additional parameter that may be passed in... */ static int debug = -1; @@ -1079,27 +1352,27 @@ int init_module(void) { - if (debug > 0) - pcnet32_debug = debug; + if (debug > 0) + pcnet32_debug = debug; - pcnet32_dev = NULL; - return pcnet32_probe(NULL); + pcnet32_dev = NULL; + return pcnet32_probe(NULL); } void cleanup_module(void) { - struct device *next_dev; + struct device *next_dev; - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (pcnet32_dev) { - next_dev = ((struct pcnet32_private *) pcnet32_dev->priv)->next; - unregister_netdev(pcnet32_dev); - release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); - kfree(pcnet32_dev->priv); - kfree(pcnet32_dev); - pcnet32_dev = next_dev; - } + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (pcnet32_dev) { + next_dev = ((struct pcnet32_private *) pcnet32_dev->priv)->next; + unregister_netdev(pcnet32_dev); + release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); + kfree(((struct pcnet32_private *)pcnet32_dev->priv)->origmem); + kfree(pcnet32_dev); + pcnet32_dev = next_dev; + } } #endif /* MODULE */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v2.2.6/linux/drivers/net/ppp.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/net/ppp.c Tue Apr 27 00:38:27 1999 @@ -4,7 +4,7 @@ * Al Longyear * Extensively rewritten by Paul Mackerras * - * ==FILEVERSION 990114== + * ==FILEVERSION 990331== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the @@ -45,9 +45,8 @@ #define PPP_MAX_RCV_QLEN 32 /* max # frames we queue up for pppd */ -/* $Id: ppp.c,v 1.19 1998/07/07 04:27:37 paulus Exp $ */ +/* $Id: ppp.c,v 1.24 1999/03/31 06:07:57 paulus Exp $ */ -#include #include #include #include @@ -61,6 +60,7 @@ #include #include #include +#include /* to get the struct task_struct */ #include /* used in new tty drivers */ #include /* used in new tty drivers */ #include @@ -90,6 +90,9 @@ #include #endif +typedef ssize_t rw_ret_t; +typedef size_t rw_count_t; + /* * Local functions */ @@ -101,9 +104,11 @@ static void ppp_async_init(struct ppp *ppp); static void ppp_async_release(struct ppp *ppp); +static int ppp_tty_sync_push(struct ppp *ppp); static int ppp_tty_push(struct ppp *ppp); static int ppp_async_encode(struct ppp *ppp); static int ppp_async_send(struct ppp *, struct sk_buff *); +static int ppp_sync_send(struct ppp *, struct sk_buff *); static int ppp_ioctl(struct ppp *, unsigned int, unsigned long); static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp); @@ -186,10 +191,10 @@ * TTY callbacks */ -static ssize_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *, - size_t); -static ssize_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *, - size_t); +static rw_ret_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *, + rw_count_t); +static rw_ret_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *, + rw_count_t); static int ppp_tty_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static unsigned int ppp_tty_poll(struct tty_struct *tty, struct file *filp, @@ -236,7 +241,6 @@ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; -EXPORT_SYMBOL(ppp_crc16_table); #ifdef CHECK_CHARACTERS static __u32 paritytab[8] = @@ -458,13 +462,13 @@ * Read a PPP frame from the rcv_q list, * waiting if necessary */ -static ssize_t +static rw_ret_t ppp_tty_read(struct tty_struct *tty, struct file *file, __u8 * buf, - size_t nr) + rw_count_t nr) { struct ppp *ppp = tty2ppp (tty); struct sk_buff *skb; - ssize_t len, err; + rw_ret_t len, err; /* * Validate the pointers @@ -546,9 +550,9 @@ * Writing to a tty in ppp line discipline sends a PPP frame. * Used by pppd to send control packets (LCP, etc.). */ -static ssize_t +static rw_ret_t ppp_tty_write(struct tty_struct *tty, struct file *file, const __u8 * data, - size_t count) + rw_count_t count) { struct ppp *ppp = tty2ppp (tty); __u8 *new_data; @@ -600,7 +604,7 @@ */ ppp_send_ctrl(ppp, skb); - return (ssize_t) count; + return (rw_ret_t) count; } /* @@ -799,6 +803,135 @@ } /* + * Send a packet to the peer over a synchronous tty line. + * All encoding and FCS are handled by hardware. + * Addr/Ctrl and Protocol field compression implemented. + * Returns -1 iff the packet could not be accepted at present, + * 0 if the packet was accepted but we can't accept another yet, or + * 1 if we can accept another packet immediately. + * If this procedure returns 0, ppp_output_wakeup will be called + * exactly once. + */ +static int +ppp_sync_send(struct ppp *ppp, struct sk_buff *skb) +{ + unsigned char *data; + int islcp; + + CHECK_PPP(0); + + if (ppp->tpkt != NULL) + return -1; + ppp->tpkt = skb; + + data = ppp->tpkt->data; + + /* + * LCP packets with code values between 1 (configure-reqest) + * and 7 (code-reject) must be sent as though no options + * had been negotiated. + */ + islcp = PPP_PROTOCOL(data) == PPP_LCP + && 1 <= data[PPP_HDRLEN] && data[PPP_HDRLEN] <= 7; + + /* only reset idle time for data packets */ + if (PPP_PROTOCOL(data) < 0x8000) + ppp->last_xmit = jiffies; + ++ppp->stats.ppp_opackets; + ppp->stats.ppp_ooctects += ppp->tpkt->len; + + if ( !(data[2]) && (ppp->flags & SC_COMP_PROT) ) { + /* compress protocol field */ + data[2] = data[1]; + data[1] = data[0]; + skb_pull(ppp->tpkt,1); + data = ppp->tpkt->data; + } + + /* + * Do address/control compression + */ + if ((ppp->flags & SC_COMP_AC) && !islcp + && PPP_ADDRESS(data) == PPP_ALLSTATIONS + && PPP_CONTROL(data) == PPP_UI) { + /* strip addr and control field */ + skb_pull(ppp->tpkt,2); + } + + return ppp_tty_sync_push(ppp); +} + +/* + * Push a synchronous frame out to the tty. + * Returns 1 if frame accepted (or discarded), 0 otherwise. + */ +static int +ppp_tty_sync_push(struct ppp *ppp) +{ + int sent; + struct tty_struct *tty = ppp2tty(ppp); + unsigned long flags; + + CHECK_PPP(0); + + if (ppp->tpkt == NULL) + return 0; + + /* prevent reentrancy with tty_pushing flag */ + save_flags(flags); + cli(); + if (ppp->tty_pushing) { + /* record wakeup attempt so we don't loose */ + /* a wakeup call while doing push processing */ + ppp->woke_up=1; + restore_flags(flags); + return 0; + } + ppp->tty_pushing = 1; + restore_flags(flags); + + if (tty == NULL || tty->disc_data != (void *) ppp) + goto flush; + + for(;;){ + ppp->woke_up=0; + + /* Note: Sync driver accepts complete frame or nothing */ + tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + sent = tty->driver.write(tty, 0, ppp->tpkt->data, ppp->tpkt->len); + if (sent < 0) { + /* write error (possible loss of CD) */ + /* record error and discard current packet */ + ppp->stats.ppp_oerrors++; + break; + } + ppp->stats.ppp_obytes += sent; + if (sent < ppp->tpkt->len) { + /* driver unable to accept frame just yet */ + save_flags(flags); + cli(); + if (ppp->woke_up) { + /* wake up called while processing */ + /* try to send the frame again */ + restore_flags(flags); + continue; + } + /* wait for wakeup callback to try send again */ + ppp->tty_pushing = 0; + restore_flags(flags); + return 0; + } + break; + } +flush: + /* done with current packet (sent or discarded) */ + kfree_skb(ppp->tpkt); + ppp->tpkt = 0; + ppp->tty_pushing = 0; + return 1; +} + +/* * Send a packet to the peer over an async tty line. * Returns -1 iff the packet could not be accepted at present, * 0 if the packet was accepted but we can't accept another yet, or @@ -830,6 +963,9 @@ { int avail, sent, done = 0; struct tty_struct *tty = ppp2tty(ppp); + + if ( ppp->flags & SC_SYNC ) + return ppp_tty_sync_push(ppp); CHECK_PPP(0); if (ppp->tty_pushing) @@ -1028,6 +1164,73 @@ ppp->stats.ppp_ibytes += count; skb = ppp->rpkt; + + if ( ppp->flags & SC_SYNC ) { + /* synchronous mode */ + + if (ppp->toss==0xE0) { + /* this is the 1st frame, reset vj comp */ + ppp_receive_error(ppp); + ppp->toss = 0; + } + + /* + * Allocate an skbuff for frame. + * The 128 is room for VJ header expansion. + */ + + if (skb == NULL) + skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN); + + if (skb == NULL) { + if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "couldn't " + "alloc skb for recv\n"); + } else { + /* + * Decompress A/C and protocol compression here. + */ + p = skb_put(skb, 2); + p[0] = PPP_ALLSTATIONS; + p[1] = PPP_UI; + if (*data == PPP_ALLSTATIONS) { + data += 2; + count -= 2; + } + if ((*data & 1) != 0) { + p = skb_put(skb, 1); + p[0] = 0; + } + + /* copy frame to socket buffer */ + p = skb_put(skb, count); + memcpy(p,data,count); + + /* + * Check if we've overflowed the MRU + */ + if (skb->len >= ppp->mru + PPP_HDRLEN + 2 + || skb_tailroom(skb) <= 0) { + ++ppp->estats.rx_length_errors; + if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "rcv frame too long: " + "len=%d mru=%d hroom=%d troom=%d\n", + skb->len, ppp->mru, skb_headroom(skb), + skb_tailroom(skb)); + } else { + if (!ppp_receive_frame(ppp, skb)) { + kfree_skb(skb); + ppp_receive_error(ppp); + } + } + + /* Reset for the next frame */ + skb = NULL; + } + ppp->rpkt = skb; + return; + } + while (count-- > 0) { /* * Collect the character and error condition for the character. @@ -1291,9 +1494,6 @@ CHECK_PPP_MAGIC(ppp); - /* ppp_dev_close may be called with tbusy==1 so we must set it to 0 */ - dev->tbusy=0; - MOD_DEC_USE_COUNT; return 0; @@ -1850,23 +2050,25 @@ return 0; } - /* - * Verify the FCS of the frame and discard the FCS characters - * from the end of the buffer. - */ - if (ppp->rfcs != PPP_GOODFCS) { - if (ppp->flags & SC_DEBUG) { - printk(KERN_DEBUG - "ppp: frame with bad fcs, length = %d\n", - count); - ppp_print_buffer("bad frame", data, count); + if ( !(ppp->flags & SC_SYNC) ) { + /* + * Verify the FCS of the frame and discard the FCS characters + * from the end of the buffer. + */ + if (ppp->rfcs != PPP_GOODFCS) { + if (ppp->flags & SC_DEBUG) { + printk(KERN_DEBUG + "ppp: frame with bad fcs, length = %d\n", + count); + ppp_print_buffer("bad frame", data, count); + } + ++ppp->estats.rx_crc_errors; + return 0; } - ++ppp->estats.rx_crc_errors; - return 0; + count -= 2; /* ignore the fcs characters */ + skb_trim(skb, count); } - count -= 2; /* ignore the fcs characters */ - skb_trim(skb, count); - + /* * Process the active decompressor. */ @@ -2055,7 +2257,7 @@ return 0; new_count = slhc_uncompress(ppp->slcomp, skb->data + PPP_HDRLEN, skb->len - PPP_HDRLEN); - if (new_count<=0) { + if (new_count <= 0) { if (ppp->flags & SC_DEBUG) printk(KERN_NOTICE "ppp: error in VJ decompression\n"); @@ -2234,7 +2436,10 @@ /* * Send the frame */ - ret = ppp_async_send(ppp, skb); + if ( ppp->flags & SC_SYNC ) + ret = ppp_sync_send(ppp, skb); + else + ret = ppp_async_send(ppp, skb); if (ret > 0) { /* we can release the lock */ ppp->xmit_busy = 0; diff -u --recursive --new-file v2.2.6/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c --- v2.2.6/linux/drivers/net/rrunner.c Tue Dec 22 14:16:56 1998 +++ linux/drivers/net/rrunner.c Sat Apr 24 17:51:48 1999 @@ -59,15 +59,7 @@ * stack will need to know about I/O vectors or something similar. */ -static const char *version = "rrunner.c: v0.09 12/14/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; - -static unsigned int read_eeprom(struct rr_private *rrpriv, - unsigned long offset, - unsigned char *buf, - unsigned long length); -static u32 read_eeprom_word(struct rr_private *rrpriv, - void * offset); -static int rr_load_firmware(struct device *dev); +static const char __initdata *version = "rrunner.c: v0.17 03/09/99 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; /* @@ -78,44 +70,32 @@ extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; +static int probed __initdata = 0; + __initfunc(int rr_hippi_probe (struct device *dev)) { - static int i = 0; int boards_found = 0; int version_disp; /* was version info already displayed? */ - u8 pci_bus; /* PCI bus number (0-255) */ - u8 pci_dev_fun; /* PCI device and function numbers (0-255) */ + struct pci_dev *pdev = NULL; + struct pci_dev *opdev = NULL; u8 pci_latency; - u16 command; /* PCI Configuration space Command register */ - unsigned int tmp; - u8 irq; struct rr_private *rrpriv; + if (probed) + return -ENODEV; + probed++; + if (!pci_present()) /* is PCI BIOS even present? */ return -ENODEV; version_disp = 0; - for (; i < 255; i++) + while((pdev = pci_find_device(PCI_VENDOR_ID_ESSENTIAL, + PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, + pdev))) { - if (pcibios_find_device(PCI_VENDOR_ID_ESSENTIAL, - PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, - i, &pci_bus, &pci_dev_fun) != 0) - break; - - pcibios_read_config_word(pci_bus, pci_dev_fun, - PCI_COMMAND, &command); - - /* Enable mastering */ - - command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_dev_fun, - PCI_COMMAND, command); - - if (!(command & PCI_COMMAND_MEMORY)){ - printk("shared mem not enabled - unable to configure RoadRunner\n"); - break; - } + if (pdev == opdev) + return 0; /* * So we found our HIPPI ... time to tell the system. @@ -123,31 +103,24 @@ dev = init_hippi_dev(dev, sizeof(struct rr_private)); - if (dev == NULL) + if (!dev) break; if (!dev->priv) dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL); - rrpriv = (struct rr_private *)dev->priv; - - /* Read register base address from - PCI Configuration Space */ - - pcibios_read_config_dword(pci_bus, pci_dev_fun, - PCI_BASE_ADDRESS_0, &tmp); + if (!dev->priv) + return -ENOMEM; - pcibios_read_config_byte(pci_bus, pci_dev_fun, - PCI_INTERRUPT_LINE, &irq); + rrpriv = (struct rr_private *)dev->priv; + memset(rrpriv, 0, sizeof(*rrpriv)); - dev->irq = irq; - rrpriv->pci_bus = pci_bus; - rrpriv->pci_dev_fun = pci_dev_fun; - sprintf(rrpriv->name, "RoadRunner serial HIPPI"); #ifdef __SMP__ spin_lock_init(&rrpriv->lock); #endif + sprintf(rrpriv->name, "RoadRunner serial HIPPI"); + dev->irq = pdev->irq; dev->open = &rr_open; dev->hard_start_xmit = &rr_start_xmit; dev->stop = &rr_close; @@ -168,29 +141,30 @@ printk(version); } - printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI at 0x%08x, irq %i\n", - dev->name, tmp, dev->irq); - - pcibios_read_config_byte(pci_bus, pci_dev_fun, - PCI_LATENCY_TIMER, &pci_latency); -#if 0 - if (pci_latency <= 48){ - printk(" PCI latency counter too low (%i), setting to 48 clocks\n", pci_latency); - pcibios_write_config_byte(pci_bus, pci_dev_fun, - PCI_LATENCY_TIMER, 48); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency <= 0x58){ + pci_latency = 0x58; + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, + pci_latency); } -#else - if (pci_latency <= 0x58) - pcibios_write_config_byte(pci_bus, pci_dev_fun, - PCI_LATENCY_TIMER, 0x58); -#endif + + pci_set_master(pdev); + + printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI " + "at 0x%08lx, irq %i, PCI latency %i\n", dev->name, + pdev->base_address[0], dev->irq, pci_latency); + /* * Remap the regs into kernel space. */ - rrpriv->regs = (struct rr_regs *)ioremap(tmp, 0x1000); + rrpriv->regs = (struct rr_regs *) + ioremap(pdev->base_address[0], 0x1000); + if (!rrpriv->regs){ - printk(KERN_ERR "%s: Unable to map I/O register, RoadRunner %i will be disabled.\n", dev->name, i); + printk(KERN_ERR "%s: Unable to map I/O register, " + "RoadRunner %i will be disabled.\n", + dev->name, boards_found); break; } @@ -198,7 +172,7 @@ * Don't access any registes before this point! */ #ifdef __BIG_ENDIAN - regs->HostCtrl |= NO_SWAP; + writel(readl(®s->HostCtrl) | NO_SWAP, ®s->HostCtrl); #endif /* * Need to add a case for little-endian 64-bit hosts here. @@ -209,6 +183,7 @@ boards_found++; dev->base_addr = 0; dev = NULL; + opdev = pdev; } /* @@ -217,12 +192,59 @@ * 1 or more boards. Otherwise, return failure (-ENODEV). */ +#ifdef MODULE + return boards_found; +#else if (boards_found > 0) return 0; else return -ENODEV; +#endif +} + +static struct device *root_dev = NULL; + +#ifdef MODULE +#if LINUX_VERSION_CODE > 0x20118 +MODULE_AUTHOR("Jes Sorensen "); +MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver"); +#endif + + +int init_module(void) +{ + int cards; + + root_dev = NULL; + + cards = rr_hippi_probe(NULL); + return cards ? 0 : -ENODEV; } +void cleanup_module(void) +{ + struct rr_private *rr; + struct device *next; + + while (root_dev) { + next = ((struct rr_private *)root_dev->priv)->next; + rr = (struct rr_private *)root_dev->priv; + + if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){ + printk(KERN_ERR "%s: trying to unload running NIC\n", + root_dev->name); + writel(HALT_NIC, &rr->regs->HostCtrl); + } + + iounmap(rr->regs); + unregister_hipdev(root_dev); + kfree(root_dev); + + root_dev = next; + } +} +#endif + /* * Commands are considered to be slow, thus there is no reason to @@ -238,21 +260,25 @@ * This is temporary - it will go away in the final version. * We probably also want to make this function inline. */ - if (regs->HostCtrl & NIC_HALTED){ - printk("issuing command for halted NIC, code 0x%x, HostCtrl %08x\n", cmd->code, regs->HostCtrl); - if (regs->Mode & FATAL_ERR) - printk("error code %02x\n", regs->Fail1); + if (readl(®s->HostCtrl) & NIC_HALTED){ + printk("issuing command for halted NIC, code 0x%x, " + "HostCtrl %08x\n", cmd->code, readl(®s->HostCtrl)); + if (readl(®s->Mode) & FATAL_ERR) + printk("error codes Fail1 %02x, Fail2 %02x\n", + readl(®s->Fail1), readl(®s->Fail2)); } idx = rrpriv->info->cmd_ctrl.pi; - regs->CmdRing[idx] = *(u32*)(cmd); + writel(*(u32*)(cmd), ®s->CmdRing[idx]); + mb(); idx = (idx - 1) % CMD_RING_ENTRIES; rrpriv->info->cmd_ctrl.pi = idx; + mb(); - if (regs->Mode & FATAL_ERR) - printk("error code %02x\n", regs->Fail1); + if (readl(®s->Mode) & FATAL_ERR) + printk("error code %02x\n", readl(®s->Fail1)); } @@ -273,85 +299,97 @@ rr_load_firmware(dev); - regs->TX_state = 0x01000000; - regs->RX_state = 0xff800000; - regs->AssistState = 0; - regs->LocalCtrl = CLEAR_INTA; - regs->BrkPt = 0x01; - regs->Timer = 0; - regs->TimerRef = 0; - regs->DmaReadState = RESET_DMA; - regs->DmaWriteState = RESET_DMA; - regs->DmaWriteHostHi = 0; - regs->DmaWriteHostLo = 0; - regs->DmaReadHostHi = 0; - regs->DmaReadHostLo = 0; - regs->DmaReadLen = 0; - regs->DmaWriteLen = 0; - regs->DmaWriteLcl = 0; - regs->DmaWriteIPchecksum = 0; - regs->DmaReadLcl = 0; - regs->DmaReadIPchecksum = 0; - regs->PciState = 0; /* 0x90 for GE? */ - regs->Mode = SWAP_DATA; + writel(0x01000000, ®s->TX_state); + writel(0xff800000, ®s->RX_state); + writel(0, ®s->AssistState); + writel(CLEAR_INTA, ®s->LocalCtrl); + writel(0x01, ®s->BrkPt); + writel(0, ®s->Timer); + writel(0, ®s->TimerRef); + writel(RESET_DMA, ®s->DmaReadState); + writel(RESET_DMA, ®s->DmaWriteState); + writel(0, ®s->DmaWriteHostHi); + writel(0, ®s->DmaWriteHostLo); + writel(0, ®s->DmaReadHostHi); + writel(0, ®s->DmaReadHostLo); + writel(0, ®s->DmaReadLen); + writel(0, ®s->DmaWriteLen); + writel(0, ®s->DmaWriteLcl); + writel(0, ®s->DmaWriteIPchecksum); + writel(0, ®s->DmaReadLcl); + writel(0, ®s->DmaReadIPchecksum); + writel(0, ®s->PciState); +#if (BITS_PER_LONG == 64) && defined __LITTLE_ENDIAN + writel(SWAP_DATA | PTR64BIT | PTR_WD_SWAP, ®s->Mode); +#elif (BITS_PER_LONG == 64) + writel(SWAP_DATA | PTR64BIT | PTR_WD_NOSWAP, ®s->Mode); +#else + writel(SWAP_DATA | PTR32BIT | PTR_WD_NOSWAP, ®s->Mode); +#endif #if 0 /* * Don't worry, this is just black magic. */ - regs->RxBase = 0xdf000; - regs->RxPrd = 0xdf000; - regs->RxCon = 0xdf000; - regs->TxBase = 0xce000; - regs->TxPrd = 0xce000; - regs->TxCon = 0xce000; - regs->RxIndPro = 0; - regs->RxIndCon = 0; - regs->RxIndRef = 0; - regs->TxIndPro = 0; - regs->TxIndCon = 0; - regs->TxIndRef = 0; - regs->pad10[0] = 0xcc000; - regs->DrCmndPro = 0; - regs->DrCmndCon = 0; - regs->DwCmndPro = 0; - regs->DwCmndCon = 0; - regs->DwCmndRef = 0; - regs->DrDataPro = 0; - regs->DrDataCon = 0; - regs->DrDataRef = 0; - regs->DwDataPro = 0; - regs->DwDataCon = 0; - regs->DwDataRef = 0; + writel(0xdf000, ®s->RxBase); + writel(0xdf000, ®s->RxPrd); + writel(0xdf000, ®s->RxCon); + writel(0xce000, ®s->TxBase); + writel(0xce000, ®s->TxPrd); + writel(0xce000, ®s->TxCon); + writel(0, ®s->RxIndPro); + writel(0, ®s->RxIndCon); + writel(0, ®s->RxIndRef); + writel(0, ®s->TxIndPro); + writel(0, ®s->TxIndCon); + writel(0, ®s->TxIndRef); + writel(0xcc000, ®s->pad10[0]); + writel(0, ®s->DrCmndPro); + writel(0, ®s->DrCmndCon); + writel(0, ®s->DwCmndPro); + writel(0, ®s->DwCmndCon); + writel(0, ®s->DwCmndRef); + writel(0, ®s->DrDataPro); + writel(0, ®s->DrDataCon); + writel(0, ®s->DrDataRef); + writel(0, ®s->DwDataPro); + writel(0, ®s->DwDataCon); + writel(0, ®s->DwDataRef); #endif - regs->MbEvent = 0xffffffff; - regs->Event = 0; + writel(0xffffffff, ®s->MbEvent); + writel(0, ®s->Event); - regs->TxPi = 0; - regs->IpRxPi = 0; + writel(0, ®s->TxPi); + writel(0, ®s->IpRxPi); - regs->EvtCon = 0; - regs->EvtPrd = 0; + writel(0, ®s->EvtCon); + writel(0, ®s->EvtPrd); rrpriv->info->evt_ctrl.pi = 0; for (i = 0; i < CMD_RING_ENTRIES; i++) - regs->CmdRing[i] = 0; + writel(0, ®s->CmdRing[i]); - regs->PciState = 0; +/* + * Why 32 ? is this not cache line size dependant? + */ + writel(WBURST_32, ®s->PciState); + mb(); - start_pc = read_eeprom_word(rrpriv, &hw->rncd_info.FwStart); + start_pc = rr_read_eeprom_word(rrpriv, &hw->rncd_info.FwStart); #if (DEBUG > 1) printk("%s: Executing firmware at address 0x%06x\n", dev->name, start_pc); #endif - regs->Pc = start_pc + 0x800; + writel(start_pc + 0x800, ®s->Pc); + mb(); udelay(5); - regs->Pc = start_pc; + writel(start_pc, ®s->Pc); + mb(); return 0; } @@ -360,7 +398,7 @@ /* * Read a string from the EEPROM. */ -static unsigned int read_eeprom(struct rr_private *rrpriv, +static unsigned int rr_read_eeprom(struct rr_private *rrpriv, unsigned long offset, unsigned char *buf, unsigned long length) @@ -368,22 +406,25 @@ struct rr_regs *regs = rrpriv->regs; u32 misc, io, host, i; - io = regs->ExtIo; - regs->ExtIo = 0; - misc = regs->LocalCtrl; - regs->LocalCtrl = 0; - host = regs->HostCtrl; - regs->HostCtrl |= HALT_NIC; + io = readl(®s->ExtIo); + writel(0, ®s->ExtIo); + misc = readl(®s->LocalCtrl); + writel(0, ®s->LocalCtrl); + host = readl(®s->HostCtrl); + writel(host | HALT_NIC, ®s->HostCtrl); + mb(); for (i = 0; i < length; i++){ - regs->WinBase = (EEPROM_BASE + ((offset+i) << 3)); - buf[i] = (regs->WinData >> 24) & 0xff; + writel((EEPROM_BASE + ((offset+i) << 3)), ®s->WinBase); + mb(); + buf[i] = (readl(®s->WinData) >> 24) & 0xff; + mb(); } - regs->HostCtrl = host; - regs->LocalCtrl = misc; - regs->ExtIo = io; - + writel(host, ®s->HostCtrl); + writel(misc, ®s->LocalCtrl); + writel(io, ®s->ExtIo); + mb(); return i; } @@ -392,13 +433,13 @@ * Shortcut to read one word (4 bytes) out of the EEPROM and convert * it to our CPU byte-order. */ -static u32 read_eeprom_word(struct rr_private *rrpriv, +static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset) { u32 word; - if ((read_eeprom(rrpriv, (unsigned long)offset, - (char *)&word, 4) == 4)) + if ((rr_read_eeprom(rrpriv, (unsigned long)offset, + (char *)&word, 4) == 4)) return be32_to_cpu(word); return 0; } @@ -410,38 +451,42 @@ * This is only called when the firmware is not running. */ static unsigned int write_eeprom(struct rr_private *rrpriv, - unsigned long offset, - unsigned char *buf, - unsigned long length) + unsigned long offset, + unsigned char *buf, + unsigned long length) { struct rr_regs *regs = rrpriv->regs; u32 misc, io, data, i, j, ready, error = 0; - io = regs->ExtIo; - regs->ExtIo = 0; - misc = regs->LocalCtrl; - regs->LocalCtrl = ENABLE_EEPROM_WRITE; + io = readl(®s->ExtIo); + writel(0, ®s->ExtIo); + misc = readl(®s->LocalCtrl); + writel(ENABLE_EEPROM_WRITE, ®s->LocalCtrl); + mb(); for (i = 0; i < length; i++){ - regs->WinBase = (EEPROM_BASE + ((offset+i) << 3)); + writel((EEPROM_BASE + ((offset+i) << 3)), ®s->WinBase); + mb(); data = buf[i] << 24; /* * Only try to write the data if it is not the same * value already. */ - if ((regs->WinData & 0xff000000) != data){ - regs->WinData = data; + if ((readl(®s->WinData) & 0xff000000) != data){ + writel(data, ®s->WinData); ready = 0; j = 0; mb(); while(!ready){ - udelay(1000); - if ((regs->WinData & 0xff000000) == data) + udelay(20); + if ((readl(®s->WinData) & 0xff000000) == + data) ready = 1; + mb(); if (j++ > 5000){ printk("data mismatch: %08x, " "WinData %08x\n", data, - regs->WinData); + readl(®s->WinData)); ready = 1; error = 1; } @@ -449,8 +494,9 @@ } } - regs->LocalCtrl = misc; - regs->ExtIo = io; + writel(misc, ®s->LocalCtrl); + writel(io, ®s->ExtIo); + mb(); return error; } @@ -465,7 +511,8 @@ rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; - rev = regs->FwRev; + rev = readl(®s->FwRev); + rrpriv->fw_rev = rev; if (rev > 0x00020024) printk(" Firmware revision: %i.%i.%i\n", (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff)); @@ -477,13 +524,13 @@ printk(" Firmware revision too old: %i.%i.%i, please " "upgrade to 2.0.37 or later.\n", (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff)); - return -EFAULT; - } - printk(" Maximum receive rings %i\n", regs->MaxRxRng); +#if (DEBUG > 2) + printk(" Maximum receive rings %i\n", readl(®s->MaxRxRng)); +#endif - sram_size = read_eeprom_word(rrpriv, (void *)8); + sram_size = rr_read_eeprom_word(rrpriv, (void *)8); printk(" SRAM size 0x%06x\n", sram_size); if (sysctl_rmem_max < 262144){ @@ -498,6 +545,9 @@ sysctl_wmem_max = 262144; } + rrpriv->next = root_dev; + root_dev = dev; + return 0; } @@ -507,7 +557,7 @@ struct rr_private *rrpriv; struct rr_regs *regs; u32 hostctrl; - unsigned long myjif, flags, tmp_ptr; + unsigned long myjif, flags; struct cmd cmd; short i; @@ -516,8 +566,9 @@ spin_lock_irqsave(&rrpriv->lock, flags); - hostctrl = regs->HostCtrl; - regs->HostCtrl |= HALT_NIC; + hostctrl = readl(®s->HostCtrl); + writel(hostctrl | HALT_NIC | RR_CLEAR_INT, ®s->HostCtrl); + mb(); if (hostctrl & PARITY_ERR){ printk("%s: Parity error halting NIC - this is serious!\n", @@ -526,31 +577,14 @@ return -EFAULT; } - - memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); - memset(rrpriv->info, 0, sizeof(struct rr_info)); - - tmp_ptr = virt_to_bus((void *)rrpriv->rx_ctrl); -#if (BITS_PER_LONG == 64) - regs->RxRingHi = (tmp_ptr >> 32); -#else - regs->RxRingHi = 0; -#endif - regs->RxRingLo = ((tmp_ptr) & 0xffffffff); - - tmp_ptr = virt_to_bus((void *)rrpriv->info); -#if (BITS_PER_LONG == 64) - regs->InfoPtrHi = (tmp_ptr >> 32); -#else - regs->InfoPtrHi = 0; -#endif - regs->InfoPtrLo = ((tmp_ptr) & 0xffffffff); + set_rxaddr(regs, rrpriv->rx_ctrl); + set_infoaddr(regs, rrpriv->info); rrpriv->info->evt_ctrl.entry_size = sizeof(struct event); rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES; rrpriv->info->evt_ctrl.mode = 0; rrpriv->info->evt_ctrl.pi = 0; - rrpriv->info->evt_ctrl.rngptr = virt_to_bus(rrpriv->evt_ring); + set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring); rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd); rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES; @@ -558,20 +592,19 @@ rrpriv->info->cmd_ctrl.pi = 15; for (i = 0; i < CMD_RING_ENTRIES; i++) { - regs->CmdRing[i] = 0; + writel(0, ®s->CmdRing[i]); } for (i = 0; i < TX_RING_ENTRIES; i++) { rrpriv->tx_ring[i].size = 0; - rrpriv->tx_ring[i].addr = 0; + set_rraddr(&rrpriv->tx_ring[i].addr, 0); rrpriv->tx_skbuff[i] = 0; } - rrpriv->info->tx_ctrl.entry_size = sizeof(struct tx_desc); rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES; rrpriv->info->tx_ctrl.mode = 0; rrpriv->info->tx_ctrl.pi = 0; - rrpriv->info->tx_ctrl.rngptr = virt_to_bus(rrpriv->tx_ring); + set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring); /* * Set dirty_tx before we start receiving interrupts, otherwise @@ -585,14 +618,20 @@ rr_reset(dev); - regs->IntrTmr = 0x60; - regs->WriteDmaThresh = 0x80 | 0x1f; - regs->ReadDmaThresh = 0x80 | 0x1f; + writel(0x60, ®s->IntrTmr); + /* + * These seem to have no real effect as the Firmware sets + * it's own default values + */ + writel(0x10, ®s->WriteDmaThresh); + writel(0x20, ®s->ReadDmaThresh); rrpriv->fw_running = 0; + mb(); hostctrl &= ~(HALT_NIC | INVALID_INST_B | PARITY_ERR); - regs->HostCtrl = hostctrl; + writel(hostctrl, ®s->HostCtrl); + mb(); spin_unlock_irqrestore(&rrpriv->lock, flags); @@ -626,10 +665,7 @@ if ((((unsigned long)skb->data) & 0xfff) > ~65320) printk("skb alloc error\n"); -#if (BITS_PER_LONG == 32) - rrpriv->rx_ring[i].zero = 0; -#endif - rrpriv->rx_ring[i].addr = virt_to_bus(skb->data); + set_rraddr(&rrpriv->rx_ring[i].addr, skb->data); rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN; } @@ -637,7 +673,8 @@ rrpriv->rx_ctrl[4].entries = RX_RING_ENTRIES; rrpriv->rx_ctrl[4].mode = 8; rrpriv->rx_ctrl[4].pi = 0; - rrpriv->rx_ctrl[4].rngptr = virt_to_bus(rrpriv->rx_ring); + mb(); + set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring); cmd.code = C_NEW_RNG; cmd.ring = 4; @@ -647,18 +684,15 @@ #if 0 { u32 tmp; - tmp = regs->ExtIo; - regs->ExtIo = 0x80; + tmp = readl(®s->ExtIo); + writel(0x80, ®s->ExtIo); i = jiffies + 1 * HZ; while (jiffies < i); - regs->ExtIo = tmp; + writel(tmp, ®s->ExtIo); } #endif dev->tbusy = 0; -#if 0 - dev->interrupt = 0; -#endif dev->start = 1; return 0; } @@ -669,24 +703,24 @@ * events) and are handled here, outside the main interrupt handler, * to reduce the size of the handler. */ -static u32 rr_handle_event(struct device *dev, u32 prodidx) +static u32 rr_handle_event(struct device *dev, u32 prodidx, u32 eidx) { struct rr_private *rrpriv; struct rr_regs *regs; - u32 tmp, eidx; + u32 tmp; rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; - eidx = rrpriv->info->evt_ctrl.pi; while (prodidx != eidx){ switch (rrpriv->evt_ring[eidx].code){ case E_NIC_UP: - tmp = regs->FwRev; + tmp = readl(®s->FwRev); printk("%s: Firmware revision %i.%i.%i up and running\n", dev->name, (tmp >> 16), ((tmp >> 8) & 0xff), (tmp & 0xff)); rrpriv->fw_running = 1; + mb(); break; case E_LINK_ON: printk("%s: Optical link ON\n", dev->name); @@ -729,7 +763,7 @@ #if (DEBUG > 2) printk("%s: RX ring valid event\n", dev->name); #endif - regs->IpRxPi = RX_RING_ENTRIES - 1; + writel(RX_RING_ENTRIES - 1, ®s->IpRxPi); break; case E_INV_RNG: printk("%s: RX ring invalid event\n", dev->name); @@ -756,35 +790,24 @@ } rrpriv->info->evt_ctrl.pi = eidx; + mb(); return eidx; } -static int rx_int(struct device *dev, u32 rxlimit) +static void rx_int(struct device *dev, u32 rxlimit, u32 index) { struct rr_private *rrpriv = (struct rr_private *)dev->priv; - u32 index, pkt_len; + u32 pkt_len; struct rr_regs *regs = rrpriv->regs; - index = rrpriv->cur_rx; - - while(index != rxlimit){ + do { pkt_len = rrpriv->rx_ring[index].size; #if (DEBUG > 2) printk("index %i, rxlimit %i\n", index, rxlimit); printk("len %x, mode %x\n", pkt_len, rrpriv->rx_ring[index].mode); #endif -#if 0 -/* - * I have never seen this occur - */ - if(!(rrpriv->rx_skbuff[index])){ - printk("Trying to receive in empty skbuff\n"); - goto out; - } -#endif - if (pkt_len > 0){ struct sk_buff *skb; @@ -808,7 +831,7 @@ skb = rrpriv->rx_skbuff[index]; skb_put(skb, pkt_len); rrpriv->rx_skbuff[index] = newskb; - rrpriv->rx_ring[index].addr = virt_to_bus(newskb->data); + set_rraddr(&rrpriv->rx_ring[index].addr, newskb->data); }else{ printk("%s: Out of memory, deferring " "packet\n", dev->name); @@ -829,13 +852,13 @@ rrpriv->rx_ring[index].size = dev->mtu + HIPPI_HLEN; if ((index & 7) == 7) - regs->IpRxPi = index; + writel(index, ®s->IpRxPi); index = (index + 1) % RX_RING_ENTRIES; - } + } while(index != rxlimit); rrpriv->cur_rx = index; - return index; + mb(); } @@ -844,25 +867,18 @@ struct rr_private *rrpriv; struct rr_regs *regs; struct device *dev = (struct device *)dev_id; - u32 prodidx, eidx, txcsmr, rxlimit, txcon; + u32 prodidx, rxindex, eidx, txcsmr, rxlimit, txcon; unsigned long flags; rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; - if (!(regs->HostCtrl & RR_INT)) + if (!(readl(®s->HostCtrl) & RR_INT)) return; -#if 0 - if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) { - printk("%s: Re-entering the interrupt handler.\n", dev->name); - return; - } -#endif - spin_lock_irqsave(&rrpriv->lock, flags); - prodidx = regs->EvtPrd; + prodidx = readl(®s->EvtPrd); txcsmr = (prodidx >> 8) & 0xff; rxlimit = (prodidx >> 16) & 0xff; prodidx &= 0xff; @@ -872,6 +888,10 @@ prodidx, rrpriv->info->evt_ctrl.pi); #endif + rxindex = rrpriv->cur_rx; + if (rxindex != rxlimit) + rx_int(dev, rxlimit, rxindex); + txcon = rrpriv->dirty_tx; if (txcsmr != txcon) { do { @@ -881,11 +901,12 @@ rrpriv->tx_skbuff[txcon] = NULL; rrpriv->tx_ring[txcon].size = 0; - rrpriv->tx_ring[txcon].addr = 0; + set_rraddr(&rrpriv->tx_ring[txcon].addr, 0); rrpriv->tx_ring[txcon].mode = 0; txcon = (txcon + 1) % TX_RING_ENTRIES; } while (txcsmr != txcon); + mb(); rrpriv->dirty_tx = txcon; if (rrpriv->tx_full && dev->tbusy && @@ -897,21 +918,15 @@ } } - rx_int(dev, rxlimit); - eidx = rrpriv->info->evt_ctrl.pi; - if (prodidx != eidx) - eidx = rr_handle_event(dev, prodidx); + eidx = rr_handle_event(dev, prodidx, eidx); eidx |= ((txcsmr << 8) | (rxlimit << 16)); - regs->EvtCon = eidx; + writel(eidx, ®s->EvtCon); + mb(); spin_unlock_irqrestore(&rrpriv->lock, flags); - -#if 0 - dev->interrupt = 0; -#endif } @@ -919,35 +934,64 @@ { struct rr_private *rrpriv; struct rr_regs *regs; + int ecode = 0; + unsigned long flags; rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; -#if 0 - regs->HostCtrl |= (HALT_NIC | RR_CLEAR_INT); -#endif + if (rrpriv->fw_rev < 0x00020000) { + printk(KERN_WARNING "%s: trying to configure device with " + "obsolete firmware\n", dev->name); + ecode = -EBUSY; + goto error; + } + + rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), + GFP_KERNEL | GFP_DMA); + if (!rrpriv->rx_ctrl) { + ecode = -ENOMEM; + goto error; + } + + rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL | GFP_DMA); + if (!rrpriv->info){ + kfree(rrpriv->rx_ctrl); + ecode = -ENOMEM; + goto error; + } + memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); + memset(rrpriv->info, 0, sizeof(struct rr_info)); + mb(); + + spin_lock_irqsave(&rrpriv->lock, flags); + writel(readl(®s->HostCtrl)|HALT_NIC|RR_CLEAR_INT, ®s->HostCtrl); + spin_unlock_irqrestore(&rrpriv->lock, flags); if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev)) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); - return -EAGAIN; + ecode = -EAGAIN; + goto error; } - rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), - GFP_KERNEL | GFP_DMA); - rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL | GFP_DMA); - rr_init1(dev); dev->tbusy = 0; -#if 0 - dev->interrupt = 0; -#endif dev->start = 1; MOD_INC_USE_COUNT; return 0; + + error: + spin_lock_irqsave(&rrpriv->lock, flags); + writel(readl(®s->HostCtrl)|HALT_NIC|RR_CLEAR_INT, ®s->HostCtrl); + spin_unlock_irqrestore(&rrpriv->lock, flags); + + dev->tbusy = 1; + dev->start = 0; + return -ENOMEM; } @@ -965,12 +1009,13 @@ printk("%s: dumping NIC TX rings\n", dev->name); printk("RxPrd %08x, TxPrd %02x, EvtPrd %08x, TxPi %02x, TxCtrlPi %02x\n", - regs->RxPrd, regs->TxPrd, regs->EvtPrd, regs->TxPi, + readl(®s->RxPrd), readl(®s->TxPrd), + readl(®s->EvtPrd), readl(®s->TxPi), rrpriv->info->tx_ctrl.pi); - printk("Error code 0x%x\n", regs->Fail1); + printk("Error code 0x%x\n", readl(®s->Fail1)); - index = (((regs->EvtPrd >> 8) & 0xff ) - 1) % EVT_RING_ENTRIES; + index = (((readl(®s->EvtPrd) >> 8) & 0xff ) - 1) % EVT_RING_ENTRIES; cons = rrpriv->dirty_tx; printk("TX ring index %i, TX consumer %i\n", index, cons); @@ -989,12 +1034,12 @@ if (rrpriv->tx_skbuff[cons]){ len = min(0x80, rrpriv->tx_skbuff[cons]->len); printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len); - printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08x), skbuff-addr %08x, truesize 0x%x\n", + printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n", rrpriv->tx_ring[cons].mode, rrpriv->tx_ring[cons].size, - rrpriv->tx_ring[cons].addr, - (unsigned int)bus_to_virt(rrpriv->tx_ring[cons].addr), - (unsigned int)rrpriv->tx_skbuff[cons]->data, + rrpriv->tx_ring[cons].addr.addrlo, + (unsigned long)bus_to_virt(rrpriv->tx_ring[cons].addr.addrlo), + (unsigned long)rrpriv->tx_skbuff[cons]->data, (unsigned int)rrpriv->tx_skbuff[cons]->truesize); for (i = 0; i < len; i++){ if (!(i & 7)) @@ -1009,7 +1054,7 @@ printk("mode 0x%x, size 0x%x, phys-addr %08x\n", rrpriv->tx_ring[i].mode, rrpriv->tx_ring[i].size, - rrpriv->tx_ring[i].addr); + rrpriv->tx_ring[i].addr.addrlo); } @@ -1033,24 +1078,26 @@ */ spin_lock(&rrpriv->lock); - tmp = regs->HostCtrl; + tmp = readl(®s->HostCtrl); if (tmp & NIC_HALTED){ printk("%s: NIC already halted\n", dev->name); rr_dump(dev); - }else - tmp |= HALT_NIC; - regs->HostCtrl = tmp; + }else{ + tmp |= HALT_NIC | RR_CLEAR_INT; + writel(tmp, ®s->HostCtrl); + mb(); + } rrpriv->fw_running = 0; - regs->TxPi = 0; - regs->IpRxPi = 0; + writel(0, ®s->TxPi); + writel(0, ®s->IpRxPi); - regs->EvtCon = 0; - regs->EvtPrd = 0; + writel(0, ®s->EvtCon); + writel(0, ®s->EvtPrd); for (i = 0; i < CMD_RING_ENTRIES; i++) - regs->CmdRing[i] = 0; + writel(0, ®s->CmdRing[i]); rrpriv->info->tx_ctrl.entries = 0; rrpriv->info->cmd_ctrl.pi = 0; @@ -1060,7 +1107,7 @@ for (i = 0; i < TX_RING_ENTRIES; i++) { if (rrpriv->tx_skbuff[i]) { rrpriv->tx_ring[i].size = 0; - rrpriv->tx_ring[i].addr = 0; + set_rraddr(&rrpriv->tx_ring[i].addr, 0); dev_kfree_skb(rrpriv->tx_skbuff[i]); } } @@ -1068,7 +1115,7 @@ for (i = 0; i < RX_RING_ENTRIES; i++) { if (rrpriv->rx_skbuff[i]) { rrpriv->rx_ring[i].size = 0; - rrpriv->rx_ring[i].addr = 0; + set_rraddr(&rrpriv->rx_ring[i].addr, 0); dev_kfree_skb(rrpriv->rx_skbuff[i]); } } @@ -1094,6 +1141,10 @@ u32 *ifield; struct sk_buff *new_skb; + if (readl(®s->Mode) & FATAL_ERR) + printk("error codes Fail1 %02x, Fail2 %02x\n", + readl(®s->Fail1), readl(®s->Fail2)); + /* * We probably need to deal with tbusy here to prevent overruns. */ @@ -1128,11 +1179,11 @@ index = txctrl->pi; rrpriv->tx_skbuff[index] = skb; - rrpriv->tx_ring[index].addr = virt_to_bus(skb->data); + set_rraddr(&rrpriv->tx_ring[index].addr, skb->data); rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */ rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END; txctrl->pi = (index + 1) % TX_RING_ENTRIES; - regs->TxPi = txctrl->pi; + writel(txctrl->pi, ®s->TxPi); if (txctrl->pi == rrpriv->dirty_tx){ rrpriv->tx_full = 1; @@ -1167,8 +1218,9 @@ { struct rr_private *rrpriv; struct rr_regs *regs; + unsigned long eptr, segptr; int i, j; - u32 localctrl, eptr, sptr, segptr, len, tmp; + u32 localctrl, sptr, len, tmp; u32 p2len, p2size, nr_seg, revision, io, sram_size; struct eeprom *hw = NULL; @@ -1178,40 +1230,44 @@ if (dev->flags & IFF_UP) return -EBUSY; - if (!(regs->HostCtrl & NIC_HALTED)){ + if (!(readl(®s->HostCtrl) & NIC_HALTED)){ printk("%s: Trying to load firmware to a running NIC.\n", dev->name); return -EBUSY; } - localctrl = regs->LocalCtrl; - regs->LocalCtrl = 0; + localctrl = readl(®s->LocalCtrl); + writel(0, ®s->LocalCtrl); - regs->EvtPrd = 0; - regs->RxPrd = 0; - regs->TxPrd = 0; + writel(0, ®s->EvtPrd); + writel(0, ®s->RxPrd); + writel(0, ®s->TxPrd); /* * First wipe the entire SRAM, otherwise we might run into all * kinds of trouble ... sigh, this took almost all afternoon * to track down ;-( */ - io = regs->ExtIo; - regs->ExtIo = 0; - sram_size = read_eeprom_word(rrpriv, (void *)8); + io = readl(®s->ExtIo); + writel(0, ®s->ExtIo); + sram_size = rr_read_eeprom_word(rrpriv, (void *)8); for (i = 200; i < sram_size / 4; i++){ - regs->WinBase = i * 4; - regs->WinData = 0; + writel(i * 4, ®s->WinBase); + mb(); + writel(0, ®s->WinData); + mb(); } - regs->ExtIo = io; + writel(io, ®s->ExtIo); + mb(); - eptr = read_eeprom_word(rrpriv, &hw->rncd_info.AddrRunCodeSegs); + eptr = (unsigned long)rr_read_eeprom_word(rrpriv, + &hw->rncd_info.AddrRunCodeSegs); eptr = ((eptr & 0x1fffff) >> 3); - p2len = read_eeprom_word(rrpriv, (void *)(0x83*4)); + p2len = rr_read_eeprom_word(rrpriv, (void *)(0x83*4)); p2len = (p2len << 2); - p2size = read_eeprom_word(rrpriv, (void *)(0x84*4)); + p2size = rr_read_eeprom_word(rrpriv, (void *)(0x84*4)); p2size = ((p2size & 0x1fffff) >> 3); if ((eptr < p2size) || (eptr > (p2size + p2len))){ @@ -1219,7 +1275,7 @@ goto out; } - revision = read_eeprom_word(rrpriv, &hw->manf.HeaderFmt); + revision = rr_read_eeprom_word(rrpriv, &hw->manf.HeaderFmt); if (revision != 1){ printk("%s: invalid firmware format (%i)\n", @@ -1227,18 +1283,18 @@ goto out; } - nr_seg = read_eeprom_word(rrpriv, (void *)eptr); + nr_seg = rr_read_eeprom_word(rrpriv, (void *)eptr); eptr +=4; #if (DEBUG > 1) printk("%s: nr_seg %i\n", dev->name, nr_seg); #endif for (i = 0; i < nr_seg; i++){ - sptr = read_eeprom_word(rrpriv, (void *)eptr); + sptr = rr_read_eeprom_word(rrpriv, (void *)eptr); eptr += 4; - len = read_eeprom_word(rrpriv, (void *)eptr); + len = rr_read_eeprom_word(rrpriv, (void *)eptr); eptr += 4; - segptr = read_eeprom_word(rrpriv, (void *)eptr); + segptr = (unsigned long)rr_read_eeprom_word(rrpriv, (void *)eptr); segptr = ((segptr & 0x1fffff) >> 3); eptr += 4; #if (DEBUG > 1) @@ -1246,16 +1302,19 @@ dev->name, i, sptr, len, segptr); #endif for (j = 0; j < len; j++){ - tmp = read_eeprom_word(rrpriv, (void *)segptr); - regs->WinBase = sptr; - regs->WinData = tmp; + tmp = rr_read_eeprom_word(rrpriv, (void *)segptr); + writel(sptr, ®s->WinBase); + mb(); + writel(tmp, ®s->WinData); + mb(); segptr += 4; sptr += 4; } } out: - regs->LocalCtrl = localctrl; + writel(localctrl, ®s->LocalCtrl); + mb(); return 0; } @@ -1291,7 +1350,7 @@ error = -ENOMEM; goto out; } - i = read_eeprom(rrpriv, 0, image, EEPROM_BYTES); + i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); if (i != EEPROM_BYTES){ kfree(image); printk(KERN_ERR "%s: Error reading EEPROM\n", @@ -1325,7 +1384,7 @@ } oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); - if (!image){ + if (!oldimage){ printk(KERN_ERR "%s: Unable to allocate memory " "for old EEPROM image\n", dev->name); error = -ENOMEM; @@ -1343,7 +1402,7 @@ printk(KERN_ERR "%s: Error writing EEPROM\n", dev->name); - i = read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES); + i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES); if (i != EEPROM_BYTES) printk(KERN_ERR "%s: Error reading back EEPROM " "image\n", dev->name); @@ -1354,7 +1413,6 @@ dev->name); error = -EFAULT; } - kfree(image); kfree(oldimage); break; @@ -1374,6 +1432,6 @@ /* * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c" + * compile-command: "gcc -D__SMP__ -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c rrunner.c" * End: */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/rrunner.h linux/drivers/net/rrunner.h --- v2.2.6/linux/drivers/net/rrunner.h Tue Dec 22 14:16:56 1998 +++ linux/drivers/net/rrunner.h Sat Apr 24 17:51:48 1999 @@ -278,7 +278,6 @@ #define TRACE_ON_WHAT_BIT 0x00020000 /* Traces on */ #define ONEM_BUF_WHAT_BIT 0x00040000 /* 1Meg vs 256K */ #define CHAR_API_WHAT_BIT 0x00080000 /* Char API vs network only */ -#define MS_DOS_WHAT_BIT 0x00100000 /* MS_DOS */ #define CMD_EVT_WHAT_BIT 0x00200000 /* Command event */ #define LONG_TX_WHAT_BIT 0x00400000 #define LONG_RX_WHAT_BIT 0x00800000 @@ -486,6 +485,63 @@ #define SAME_IFIELD 0x80 +typedef struct { +#if (BITS_PER_LONG == 64) + u64 addrlo; +#else + u32 addrhi; + u32 addrlo; +#endif +} rraddr; + + +static inline void set_rraddr(rraddr *ra, volatile void *addr) +{ + unsigned long baddr = virt_to_bus((void *)addr); +#if (BITS_PER_LONG == 64) + ra->addrlo = baddr; +#else + /* Don't bother setting zero every time */ + ra->addrlo = baddr; +#endif + mb(); +} + + +static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr) +{ + unsigned long baddr = virt_to_bus((void *)addr); +#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) + writel(baddr & 0xffffffff, ®s->RxRingHi); + writel(baddr >> 32, ®s->RxRingLo); +#elif (BITS_PER_LONG == 64) + writel(baddr >> 32, ®s->RxRingHi); + writel(baddr & 0xffffffff, ®s->RxRingLo); +#else + writel(0, ®s->RxRingHi); + writel(baddr, ®s->RxRingLo); +#endif + mb(); +} + + +static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr) +{ + unsigned long baddr = virt_to_bus((void *)addr); +#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) + writel(baddr & 0xffffffff, ®s->InfoPtrHi); + writel(baddr >> 32, ®s->InfoPtrLo); +#elif (BITS_PER_LONG == 64) + writel(baddr >> 32, ®s->InfoPtrHi); + writel(baddr & 0xffffffff, ®s->InfoPtrLo); +#else + writel(0, ®s->InfoPtrHi); + writel(baddr, ®s->InfoPtrLo); +#endif + mb(); +} + + /* * TX ring */ @@ -498,12 +554,7 @@ #define TX_RING_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc)) struct tx_desc{ -#if (BITS_PER_LONG == 64) - u64 addr; -#else - u32 zero; - u32 addr; -#endif + rraddr addr; u32 res; #ifdef __LITTLE_ENDIAN u16 size; @@ -525,12 +576,7 @@ #define RX_RING_SIZE (RX_RING_ENTRIES * sizeof(struct rx_desc)) struct rx_desc{ -#if (BITS_PER_LONG == 64) - u64 addr; -#else - u32 zero; - u32 addr; -#endif + rraddr addr; u32 res; #ifdef __LITTLE_ENDIAN u16 size; @@ -714,12 +760,7 @@ * This struct is shared with the NIC firmware. */ struct ring_ctrl { -#if (BITS_PER_LONG == 64) - u64 rngptr; -#else - u32 zero; - u32 rngptr; -#endif + rraddr rngptr; #ifdef __LITTLE_ENDIAN u16 entries; u8 pad; @@ -759,19 +800,19 @@ struct rx_desc rx_ring[RX_RING_ENTRIES]; struct tx_desc tx_ring[TX_RING_ENTRIES]; struct event evt_ring[EVT_RING_ENTRIES]; - struct sk_buff *tx_skbuff[TX_RING_ENTRIES]; struct sk_buff *rx_skbuff[RX_RING_ENTRIES]; + struct sk_buff *tx_skbuff[TX_RING_ENTRIES]; struct rr_regs *regs; /* Register base */ struct ring_ctrl *rx_ctrl; /* Receive ring control */ struct rr_info *info; /* Shared info page */ + struct device *next; spinlock_t lock; struct timer_list timer; u32 cur_rx, cur_cmd, cur_evt; u32 dirty_rx, dirty_tx; u32 tx_full; + u32 fw_rev; short fw_running; - u8 pci_bus; /* PCI bus number */ - u8 pci_dev_fun; /* PCI device numbers */ char name[24]; /* The assigned name */ struct net_device_stats stats; }; @@ -789,5 +830,11 @@ static int rr_close(struct device *dev); static struct net_device_stats *rr_get_stats(struct device *dev); static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd); +static unsigned int rr_read_eeprom(struct rr_private *rrpriv, + unsigned long offset, + unsigned char *buf, + unsigned long length); +static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset); +static int rr_load_firmware(struct device *dev); #endif /* _RRUNNER_H_ */ diff -u --recursive --new-file v2.2.6/linux/drivers/net/z85230.c linux/drivers/net/z85230.c --- v2.2.6/linux/drivers/net/z85230.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/z85230.c Sat Apr 24 17:51:48 1999 @@ -48,6 +48,7 @@ #include #include "z85230.h" +#include "syncppp.h" static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED; diff -u --recursive --new-file v2.2.6/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.2.6/linux/drivers/pci/oldproc.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/pci/oldproc.c Wed Apr 21 09:28:49 1999 @@ -445,6 +445,7 @@ DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"), DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee"), DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"), + DEVICE( AVM, AVM_A1, "A1 (Fritz)"), DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"), DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"), DEVICE( STALLION, STALLION_EIOPCI,"EasyIO"), @@ -784,6 +785,7 @@ case PCI_VENDOR_ID_O2: return "O2 Micro"; case PCI_VENDOR_ID_3DFX: return "3Dfx"; case PCI_VENDOR_ID_SIGMADES: return "Sigma Designs"; + case PCI_VENDOR_ID_AVM: return "AVM"; case PCI_VENDOR_ID_CCUBE: return "C-Cube"; case PCI_VENDOR_ID_DIPIX: return "Dipix"; case PCI_VENDOR_ID_STALLION: return "Stallion Technologies"; diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.2.6/linux/drivers/sbus/audio/audio.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/audio/audio.c Thu Apr 22 19:24:51 1999 @@ -7,6 +7,7 @@ * * Mixer code adapted from code contributed by and * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz) + * and with fixes from Michael Shuey (shuey@ecn.purdue.edu) * The mixer code cheats; Sparc hardware doesn't generally allow independent * line control, and this fakes it badly. * @@ -628,13 +629,12 @@ #define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC) static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned int *arg) { struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; - unsigned long i = 0, j = 0, k = 0; - - k = arg; + unsigned long i = 0, j = 0; + unsigned int k; if(cmd == SOUND_MIXER_INFO) { audio_device_t tmp; @@ -663,6 +663,9 @@ case SOUND_MIXER_WRITE_MIC: case SOUND_MIXER_WRITE_CD: case SOUND_MIXER_WRITE_LINE: + case SOUND_MIXER_WRITE_IMIX: + if(get_user(k, arg)) + return -EFAULT; tprintk(("setting input volume (0x%x)", k)); if (drv->ops->get_input_channels) j = drv->ops->get_input_channels(drv); @@ -692,6 +695,8 @@ case SOUND_MIXER_WRITE_PCM: case SOUND_MIXER_WRITE_VOLUME: case SOUND_MIXER_WRITE_SPEAKER: + if(get_user(k, arg)) + return -EFAULT; tprintk(("setting output volume (0x%x)", k)); if (drv->ops->get_output_channels) j = drv->ops->get_output_channels(drv); @@ -731,10 +736,13 @@ case SOUND_MIXER_WRITE_RECSRC: if (!drv->ops->set_input_port) return -EINVAL; - if (arg & SOUND_MASK_IMIX) j |= AUDIO_ANALOG_LOOPBACK; - if (arg & SOUND_MASK_CD) j |= AUDIO_CD; - if (arg & SOUND_MASK_LINE) j |= AUDIO_LINE_IN; - if (arg & SOUND_MASK_MIC) j |= AUDIO_MICROPHONE; + if(get_user(k, arg)) + return -EFAULT; + /* only one should ever be selected */ + if (k & SOUND_MASK_IMIX) j = AUDIO_ANALOG_LOOPBACK; + if (k & SOUND_MASK_CD) j = AUDIO_CD; + if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; + if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; tprintk(("setting inport to %d\n", j)); i = drv->ops->set_input_port(drv, j); @@ -790,11 +798,12 @@ j = drv->ops->get_output_balance(drv); i = b_to_s(i,j); } - return COPY_OUT((int *)arg, i); + return COPY_OUT(arg, i); case SOUND_MIXER_READ_RECLEV: case SOUND_MIXER_READ_MIC: case SOUND_MIXER_READ_CD: case SOUND_MIXER_READ_LINE: + case SOUND_MIXER_READ_IMIX: if (drv->ops->get_input_channels) j = drv->ops->get_input_channels(drv); if (j == 1) { @@ -808,7 +817,7 @@ j = drv->ops->get_input_balance(drv); i = b_to_s(i,j); } - return COPY_OUT((int *)arg, i); + return COPY_OUT(arg, i); default: return -EINVAL; } @@ -862,7 +871,7 @@ switch (minor & 0xf) { case SPARCAUDIO_MIXER_MINOR: - return sparcaudio_mixer_ioctl(inode, file, cmd, arg); + return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg); case SPARCAUDIO_DSP16_MINOR: case SPARCAUDIO_DSP_MINOR: case SPARCAUDIO_AUDIO_MINOR: diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.2.6/linux/drivers/sbus/audio/cs4231.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/audio/cs4231.c Wed Apr 28 08:47:39 1999 @@ -73,6 +73,7 @@ static int cs4231_recintr(struct sparcaudio_driver *drv); static int cs4231_output_muted(struct sparcaudio_driver *drv, int value); static void cs4231_pollinput(struct sparcaudio_driver *drv); +static void eb4231_pollinput(struct sparcaudio_driver *drv); static int cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length); static void cs4231_getsamplecount(struct sparcaudio_driver *drv, @@ -92,8 +93,8 @@ tprintk(("enabling interrupts\n")); save_flags(flags); cli(); - cs4231_chip->regs->iar = 0xa; - cs4231_chip->regs->idr = INTR_ON; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_ON); restore_flags(flags); cs4231_chip->status |= CS_STATUS_INTS_ON; @@ -111,8 +112,8 @@ tprintk(("disabling interrupts\n")); save_flags(flags); cli(); - cs4231_chip->regs->iar = 0xa; - cs4231_chip->regs->idr = INTR_OFF; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_OFF); restore_flags(flags); cs4231_chip->status &= ~CS_STATUS_INTS_ON; @@ -127,8 +128,9 @@ save_flags(flags); cli(); - cs4231_chip->regs->iar = 0x9; - cs4231_chip->regs->idr |= PEN_ENABLE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PEN_ENABLE)); restore_flags(flags); } @@ -140,8 +142,9 @@ tprintk(("disabling play\n")); save_flags(flags); cli(); - cs4231_chip->regs->iar = 0x9; - cs4231_chip->regs->idr &= PEN_DISABLE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & PEN_DISABLE)); restore_flags(flags); } @@ -153,8 +156,9 @@ tprintk(("enabling rec\n")); save_flags(flags); cli(); - cs4231_chip->regs->iar = 0x9; - cs4231_chip->regs->idr |= CEN_ENABLE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | CEN_ENABLE)); restore_flags(flags); } @@ -166,64 +170,68 @@ tprintk(("disabling rec\n")); save_flags(flags); cli(); - cs4231_chip->regs->iar = 0x9; - cs4231_chip->regs->idr &= CEN_DISABLE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & CEN_DISABLE)); restore_flags(flags); } +static struct cs4231_rates { + int speed, bits; +} cs4231_rate_table[] = { + { 5512, CS4231_DFR_5512 }, + { 6615, CS4231_DFR_6615 }, + { 8000, CS4231_DFR_8000 }, + { 9600, CS4231_DFR_9600 }, + { 11025, CS4231_DFR_11025 }, + { 16000, CS4231_DFR_16000 }, + { 18900, CS4231_DFR_18900 }, + { 22050, CS4231_DFR_22050 }, + { 27429, CS4231_DFR_27429 }, + { 32000, CS4231_DFR_32000 }, + { 33075, CS4231_DFR_33075 }, + { 37800, CS4231_DFR_37800 }, + { 44100, CS4231_DFR_44100 }, + { 48000, CS4231_DFR_48000 } +}; + +#define NUM_RATES (sizeof(cs4231_rate_table) / sizeof(struct cs4231_rates)) + static int -cs4231_rate_to_bits(struct sparcaudio_driver *drv, int value) +cs4231_rate_to_bits(struct sparcaudio_driver *drv, int *value) { - int set_bits; + struct cs4231_rates *p = &cs4231_rate_table[0]; + int i, wanted = *value; - switch (value) { - case 5512: - set_bits = CS4231_DFR_5512; - break; - case 6615: - set_bits = CS4231_DFR_6615; - break; - case 8000: - set_bits = CS4231_DFR_8000; - break; - case 9600: - set_bits = CS4231_DFR_9600; - break; - case 11025: - set_bits = CS4231_DFR_11025; - break; - case 16000: - set_bits = CS4231_DFR_16000; - break; - case 18900: - set_bits = CS4231_DFR_18900; - break; - case 22050: - set_bits = CS4231_DFR_22050; - break; - case 27429: - set_bits = CS4231_DFR_27429; - break; - case 32000: - set_bits = CS4231_DFR_32000; - break; - case 33075: - set_bits = CS4231_DFR_33075; - break; - case 37800: - set_bits = CS4231_DFR_37800; - break; - case 44100: - set_bits = CS4231_DFR_44100; - break; - case 48000: - set_bits = CS4231_DFR_48000; - break; - default: - set_bits = -(EINVAL); - break; + /* We try to be nice and approximate what the user asks for. */ + if(wanted < 5512) + wanted = 5512; + if(wanted > 48000) + wanted = 48000; + + for(i = 0; i < NUM_RATES; i++, p++) { + /* Exact match? */ + if(wanted == p->speed) + break; + + /* If we're inbetween two entries, and neither is exact, + * pick the closest one. + */ + if(wanted == p[1].speed) + continue; + if(wanted > p->speed && + wanted < p[1].speed) { + int diff1, diff2; + + diff1 = wanted - p->speed; + diff2 = p[1].speed - wanted; + if(diff2 < diff1) + p++; + break; + } } - return set_bits; + *value = p->speed; + return p->bits; } static int @@ -268,9 +276,14 @@ if (value != 0) { set_bits = cs4231_encoding_to_bits(drv, value); if (set_bits >= 0) { - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; - tmp_bits = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CHANGE_ENCODING(tmp_bits, set_bits)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); CHIP_READY @@ -298,9 +311,14 @@ if (value != 0) { set_bits = cs4231_encoding_to_bits(drv, value); if (set_bits >= 0) { - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - tmp_bits = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1c); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CHANGE_ENCODING(tmp_bits, set_bits)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); CHIP_READY @@ -326,15 +344,22 @@ tprintk(("output rate %d\n", value)); if (value != 0) { - set_bits = cs4231_rate_to_bits(drv, value); + set_bits = cs4231_rate_to_bits(drv, &value); if (set_bits >= 0) { - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; - tmp_bits = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CHANGE_DFR(tmp_bits, set_bits)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); CHIP_READY cs4231_chip->perchip_info.play.sample_rate = value; + tprintk(("tmp_bits[%02x] set_bits[%02x] CHANGE_DFR[%02x]\n", + tmp_bits, set_bits, CHANGE_DFR(tmp_bits, set_bits))); return 0; } } @@ -356,11 +381,16 @@ tprintk(("input rate %d\n", value)); if (value != 0) { - set_bits = cs4231_rate_to_bits(drv, value); + set_bits = cs4231_rate_to_bits(drv, &value); if (set_bits >= 0) { - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - tmp_bits = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1c); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CHANGE_DFR(tmp_bits, set_bits)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); CHIP_READY @@ -390,10 +420,10 @@ tmp_bits = cs4231_chip->regs->idr; switch (value) { case 1: - cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits)); break; case 2: - cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits)); break; default: dprintk(("input chan failed\n")); @@ -420,14 +450,14 @@ int tmp_bits; tprintk(("output channels %d\n", value)); - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; - tmp_bits = cs4231_chip->regs->idr; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); switch (value) { case 1: - cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits)); break; case 2: - cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits)); break; default: dprintk(("output chan failed\n")); @@ -483,14 +513,16 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; unsigned int x = 0; - cs4231_chip->regs->iar = IAR_AUTOCAL_END; - while (cs4231_chip->regs->idr == IAR_NOT_READY && x <= CS_TIMEOUT) { + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); + while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == IAR_NOT_READY && + x <= CS_TIMEOUT) { x++; } x = 0; - cs4231_chip->regs->iar = 0x0b; - while (cs4231_chip->regs->idr == AUTOCAL_IN_PROGRESS && x <= CS_TIMEOUT) { + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0b); + while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == AUTOCAL_IN_PROGRESS && + x <= CS_TIMEOUT) { x++; } } @@ -501,16 +533,20 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; tprintk(("in cs4231_output_muted: %d\n", value)); if (!value) { - cs4231_chip->regs->iar = 0x7; - cs4231_chip->regs->idr &= OUTCR_UNMUTE; - cs4231_chip->regs->iar = 0x6; - cs4231_chip->regs->idr &= OUTCR_UNMUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE)); cs4231_chip->perchip_info.output_muted = 0; } else { - cs4231_chip->regs->iar = 0x7; - cs4231_chip->regs->idr |= OUTCR_MUTE; - cs4231_chip->regs->iar = 0x6; - cs4231_chip->regs->idr |= OUTCR_MUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE)); cs4231_chip->perchip_info.output_muted = 1; } return 0; @@ -555,27 +591,33 @@ /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively * enable things. */ - cs4231_chip->regs->iar = 0x1a; - cs4231_chip->regs->idr |= MONO_IOCR_MUTE; - cs4231_chip->regs->iar = 0x0a; - cs4231_chip->regs->idr |= PINCR_LINE_MUTE; - cs4231_chip->regs->idr |= PINCR_HDPH_MUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | MONO_IOCR_MUTE)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_LINE_MUTE)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_HDPH_MUTE)); if (value & AUDIO_SPEAKER) { - cs4231_chip->regs->iar = 0x1a; - cs4231_chip->regs->idr &= ~MONO_IOCR_MUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~MONO_IOCR_MUTE)); retval |= AUDIO_SPEAKER; } if (value & AUDIO_HEADPHONE) { - cs4231_chip->regs->iar = 0x0a; - cs4231_chip->regs->idr &= ~PINCR_HDPH_MUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_HDPH_MUTE)); retval |= AUDIO_HEADPHONE; } if (value & AUDIO_LINE_OUT) { - cs4231_chip->regs->iar = 0x0a; - cs4231_chip->regs->idr &= ~PINCR_LINE_MUTE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_LINE_MUTE)); retval |= AUDIO_LINE_OUT; } @@ -605,32 +647,40 @@ /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */ /* This apparently applies only to APC ultras, not ebus ultras */ - if (!cs4231_chip->status & CS_STATUS_IS_ULTRA) { + if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) { if (value & AUDIO_INTERNAL_CD_IN) { - cs4231_chip->regs->iar = 0x1; - cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr); - cs4231_chip->regs->iar = 0x0; - cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); retval = AUDIO_INTERNAL_CD_IN; } } if ((value & AUDIO_LINE_IN)) { - cs4231_chip->regs->iar = 0x1; - cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr); - cs4231_chip->regs->iar = 0x0; - cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); retval = AUDIO_LINE_IN; } else if (value & AUDIO_MICROPHONE) { - cs4231_chip->regs->iar = 0x1; - cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr); - cs4231_chip->regs->iar = 0x0; - cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); retval = AUDIO_MICROPHONE; } else if (value & AUDIO_ANALOG_LOOPBACK) { - cs4231_chip->regs->iar = 0x1; - cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr); - cs4231_chip->regs->iar = 0x0; - cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); retval = AUDIO_ANALOG_LOOPBACK; } @@ -659,18 +709,19 @@ a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)); - cs4231_chip->regs->iar = 0x0d; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d); if (a >= CS4231_MON_MAX_ATEN) - cs4231_chip->regs->idr = LOOPB_OFF; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), LOOPB_OFF); else - cs4231_chip->regs->idr = ((a << 2) | LOOPB_ON); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), ((a << 2) | LOOPB_ON)); if (value == AUDIO_MAX_GAIN) - cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain), AUDIO_MAX_GAIN); else - cs4231_chip->perchip_info.monitor_gain = ((CS4231_MAX_DEV_ATEN - a) * - (AUDIO_MAX_GAIN + 1) / - (CS4231_MAX_DEV_ATEN + 1)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain), + ((CS4231_MAX_DEV_ATEN - a) * + (AUDIO_MAX_GAIN + 1) / + (CS4231_MAX_DEV_ATEN + 1))); return 0; } @@ -852,12 +903,12 @@ l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); - cs4231_chip->regs->iar = 0x0; - old_gain = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = RECGAIN_SET(old_gain, l_adj); - cs4231_chip->regs->iar = 0x1; - old_gain = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = RECGAIN_SET(old_gain, r_adj); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); + old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, l_adj)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); + old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, r_adj)); if (l == value) { (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / @@ -894,12 +945,12 @@ (r * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1))); - cs4231_chip->regs->iar = 0x6; - old_gain = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = GAIN_SET(old_gain, l_adj); - cs4231_chip->regs->iar = 0x7; - old_gain = cs4231_chip->regs->idr; - cs4231_chip->regs->idr = GAIN_SET(old_gain, r_adj); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); + old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, l_adj)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); + old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, r_adj)); if ((value == 0) || (value == AUDIO_MAX_GAIN)) { tmp = value; @@ -920,13 +971,16 @@ static void cs4231_chip_reset(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned char vers; tprintk(("in cs4231_chip_reset\n")); if (cs4231_chip->status & CS_STATUS_IS_EBUS) { #ifdef EB4231_SUPPORT - writel(EBUS_DCSR_RESET, &cs4231_chip->eb2p->dcsr); - writel(EBUS_DCSR_RESET, &cs4231_chip->eb2c->dcsr); + writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr)); + writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr)); #endif } else { cs4231_chip->regs->dmacsr = APC_CHIP_RESET; @@ -938,12 +992,13 @@ cs4231_chip->regs->dmacsr &= ~(APC_CDC_RESET); } - cs4231_chip->regs->iar |= IAR_AUTOCAL_BEGIN; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->iar)) | IAR_AUTOCAL_BEGIN)); CHIP_READY - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x0c; - cs4231_chip->regs->idr = MISC_IR_MODE2; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x0c); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), MISC_IR_MODE2); /* This is the equivalent of DEFAULT_DATA_FMAT */ cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW); @@ -956,25 +1011,27 @@ cs4231_set_output_channels(drv, CS4231_CHANNELS); cs4231_set_output_precision(drv, CS4231_PRECISION); - cs4231_chip->regs->iar = 0x19; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x19); + /* see what we can turn on */ - if (cs4231_chip->regs->idr & CS4231A) { + vers = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + if (vers & CS4231A) { tprintk(("This is a CS4231A\n")); cs4231_chip->status |= CS_STATUS_REV_A; } else cs4231_chip->status &= ~CS_STATUS_REV_A; - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x10; - cs4231_chip->regs->idr = OLB_ENABLE; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x10); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), OLB_ENABLE); - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x11; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x11); if (cs4231_chip->status & CS_STATUS_REV_A) - cs4231_chip->regs->idr = (HPF_ON | XTALE_ON); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (HPF_ON | XTALE_ON)); else - cs4231_chip->regs->idr = HPF_ON; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), HPF_ON); - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1a; - cs4231_chip->regs->idr = 0x00; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1a); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), 0x00); /* Now set things up for defaults */ cs4231_set_input_balance(drv, AUDIO_MID_BALANCE); @@ -988,13 +1045,14 @@ cs4231_set_monitor_volume(drv, LOOPB_OFF); - cs4231_chip->regs->iar = IAR_AUTOCAL_END; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); cs4231_ready(drv); - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x09; - cs4231_chip->regs->idr &= ACAL_DISABLE; - cs4231_chip->regs->iar = IAR_AUTOCAL_END; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x09); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), + (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ACAL_DISABLE)); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); cs4231_ready(drv); @@ -1036,24 +1094,18 @@ { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; struct audio_prinfo *thisdir; - unsigned int count, nextcount, curcount; + unsigned int count, curcount, nextcount, dbcr; - if (direction == 1) /* record */ - { - thisdir = &cs4231_chip->perchip_info.record; - curcount = - cs4231_length_to_samplecount(thisdir, readl(&cs4231_chip->eb2c->dbcr)); - nextcount = - cs4231_length_to_samplecount(thisdir, 0/*cs4231_chip->regs->dmacnc*/); - } - else /* play */ - { - thisdir = &cs4231_chip->perchip_info.play; - curcount = - cs4231_length_to_samplecount(thisdir, readl(&cs4231_chip->eb2p->dbcr)); - nextcount = - cs4231_length_to_samplecount(thisdir, 0/*cs4231_chip->regs->dmapnc*/); - } + if(direction == 1) { + thisdir = &cs4231_chip->perchip_info.record; + dbcr = readl(&(cs4231_chip->eb2c->dbcr)); + nextcount = cs4231_chip->input_next_dma_size; + } else { + thisdir = &cs4231_chip->perchip_info.play; + dbcr = readl(&(cs4231_chip->eb2p->dbcr)); + nextcount = cs4231_chip->output_next_dma_size; + } + curcount = cs4231_length_to_samplecount(thisdir, dbcr); count = thisdir->samples; length = cs4231_length_to_samplecount(thisdir, length); /* normalize for where we are. */ @@ -1131,18 +1183,16 @@ /* stop capture here or midlevel? */ cs4231_chip->perchip_info.record.open = 0; if (cs4231_chip->input_dma_handle) { -#if 0 - mmu_release_scsi_one(cs4231_chip->input_dma_handle, - cs4231_chip->input_dma_size, drv->dev->my_bus); -#endif + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + mmu_release_scsi_one(cs4231_chip->input_dma_handle, + cs4231_chip->input_dma_size, drv->dev->my_bus); cs4231_chip->input_dma_handle = 0; cs4231_chip->input_dma_size = 0; } if (cs4231_chip->input_next_dma_handle) { -#if 0 - mmu_release_scsi_one(cs4231_chip->input_next_dma_handle, - cs4231_chip->input_next_dma_size, drv->dev->my_bus); -#endif + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + mmu_release_scsi_one(cs4231_chip->input_next_dma_handle, + cs4231_chip->input_next_dma_size, drv->dev->my_bus); cs4231_chip->input_next_dma_handle = 0; cs4231_chip->input_next_dma_size = 0; } @@ -1152,19 +1202,17 @@ cs4231_chip->perchip_info.play.active = cs4231_chip->perchip_info.play.open = 0; if (cs4231_chip->output_dma_handle) { -#if 0 - mmu_release_scsi_one(cs4231_chip->output_dma_handle, - cs4231_chip->output_dma_size, drv->dev->my_bus); -#endif + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + mmu_release_scsi_one(cs4231_chip->output_dma_handle, + cs4231_chip->output_dma_size, drv->dev->my_bus); cs4231_chip->output_dma_handle = 0; cs4231_chip->output_dma_size = 0; } if (cs4231_chip->output_next_dma_handle) { -#if 0 - mmu_release_scsi_one(cs4231_chip->output_next_dma_handle, - cs4231_chip->output_next_dma_size, - drv->dev->my_bus); -#endif + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + mmu_release_scsi_one(cs4231_chip->output_next_dma_handle, + cs4231_chip->output_next_dma_size, + drv->dev->my_bus); cs4231_chip->output_next_dma_handle = 0; cs4231_chip->output_next_dma_size = 0; } @@ -1230,11 +1278,7 @@ { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int status = 0; - unsigned int dcsr; - - dcsr = readl(&cs4231_chip->eb2p->dcsr); - printk("pintr\ncsr 0x%x acr 0x%x bcr %d\n", readl(&cs4231_chip->eb2p->dcsr), readl(&cs4231_chip->eb2p->dacr), readl(&cs4231_chip->eb2p->dbcr)); if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) cs4231_chip->playlen = cs4231_chip->output_size; @@ -1244,35 +1288,24 @@ cs4231_chip->playing_count--; status++; } - -#if 0 - if (cs4231_chip->output_next_dma_handle) { + if(cs4231_chip->output_next_dma_handle) { cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle; cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size; - cs4231_chip->output_next_dma_size = 0; cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; } -#endif if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && !(cs4231_chip->perchip_info.play.pause)) { -#if 0 - if (dcsr & EBUS_DCSR_A_LOADED) { - cs4231_chip->output_next_dma_handle = virt_to_bus(cs4231_chip->output_ptr); - cs4231_chip->output_next_dma_size = cs4231_chip->output_size; - } else { -#endif - cs4231_chip->output_dma_handle = virt_to_bus(cs4231_chip->output_ptr); - cs4231_chip->output_dma_size = cs4231_chip->output_size; -#if 0 - } -#endif - writel(virt_to_bus(cs4231_chip->output_ptr), &cs4231_chip->eb2p->dacr); - writel(cs4231_chip->output_size, &cs4231_chip->eb2p->dbcr); + cs4231_chip->output_next_dma_handle = virt_to_bus(cs4231_chip->output_ptr); + cs4231_chip->output_next_dma_size = cs4231_chip->output_size; + + writel(cs4231_chip->output_next_dma_size, &(cs4231_chip->eb2p->dbcr)); + writel(cs4231_chip->output_next_dma_handle, &(cs4231_chip->eb2p->dacr)); cs4231_chip->output_size = 0; cs4231_chip->output_ptr = NULL; cs4231_chip->playing_count++; - status+=2; + status += 2; } sparcaudio_output_done(drv, status); @@ -1354,14 +1387,11 @@ if (cs4231_chip->perchip_info.record.active == 0) { dprintk(("going inactive\n")); + eb4231_pollinput(drv); cs4231_disable_rec(drv); } if (cs4231_chip->input_dma_handle) { -#if 0 - mmu_release_scsi_one(cs4231_chip->input_dma_handle, - cs4231_chip->input_dma_size, drv->dev->my_bus); -#endif cs4231_chip->input_dma_handle = 0; cs4231_chip->input_dma_size = 0; cs4231_chip->recording_count--; @@ -1378,29 +1408,17 @@ !(cs4231_chip->perchip_info.record.pause)) { cs4231_recclear(cs4231_chip->perchip_info.record.encoding, (char *)cs4231_chip->input_ptr, cs4231_chip->input_size); -#if 0 - cs4231_chip->input_next_dma_handle = - mmu_get_scsi_one((char *) cs4231_chip->input_ptr, - cs4231_chip->input_size, drv->dev->my_bus); - cs4231_chip->regs->dmacnva = cs4231_chip->input_next_dma_handle; - cs4231_chip->input_next_dma_size = cs4231_chip->regs->dmacnc = - cs4231_chip->input_size; -#else - cs4231_chip->input_next_dma_handle = cs4231_chip->eb2c->dacr = virt_to_bus(cs4231_chip->input_ptr); - cs4231_chip->input_next_dma_size = cs4231_chip->eb2c->dbcr = cs4231_chip->input_size; -#endif + + cs4231_chip->input_next_dma_handle = virt_to_bus(cs4231_chip->input_ptr); + cs4231_chip->input_next_dma_size = cs4231_chip->input_size; + + writel(cs4231_chip->input_next_dma_size, &(cs4231_chip->eb2c->dbcr)); + writel(cs4231_chip->input_next_dma_handle, &(cs4231_chip->eb2c->dacr)); + cs4231_chip->input_size = 0; cs4231_chip->input_ptr = NULL; cs4231_chip->recording_count++; status += 2; - } else { -#if 0 - cs4231_chip->regs->dmacnva = 0; - cs4231_chip->regs->dmacnc = 0; -#else - cs4231_chip->eb2c->dacr = 0; - cs4231_chip->eb2c->dbcr = 0; -#endif } sparcaudio_input_done(drv, 1); @@ -1416,7 +1434,6 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; unsigned int dcsr; - dprintk(("in eb4231 start output act %d pau %d\n", cs4231_chip->perchip_info.play.active, cs4231_chip->perchip_info.play.pause)); cs4231_chip->output_ptr = buffer; cs4231_chip->output_size = count; @@ -1431,17 +1448,19 @@ dcsr = readl(&cs4231_chip->eb2p->dcsr); if (!(dcsr & EBUS_DCSR_EN_DMA)) { - dprintk(("about to go setup\n")); + writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr)); - dcsr = EB2_PLAY_SETUP; - writel(dcsr, (unsigned long)&cs4231_chip->eb2p->dcsr); eb4231_playintr(drv); - dprintk(("enabling\n")); + + writel(EBUS_DCSR_BURST_SZ_16 | + (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), + &(cs4231_chip->eb2p->dcsr)); + cs4231_enable_play(drv); cs4231_ready(drv); } else { - dprintk(("playing next block\n")); eb4231_playintr(drv); } } @@ -1484,21 +1503,28 @@ static void eb4231_stop_output(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int dcsr; - dprintk(("in cs4231_stop_output\n")); - dprintk(("csr 0x%x acr 0x%x bcr %d\n", readl(&cs4231_chip->eb2p->dcsr), readl(&cs4231_chip->eb2p->dacr), readl(&cs4231_chip->eb2p->dbcr))); + dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n", + readl(&cs4231_chip->eb2p->dcsr), + readl(&cs4231_chip->eb2p->dacr), + readl(&cs4231_chip->eb2p->dbcr))); cs4231_chip->output_ptr = NULL; cs4231_chip->output_size = 0; if (cs4231_chip->output_dma_handle) { cs4231_chip->output_dma_handle = 0; cs4231_chip->output_dma_size = 0; } -#if 0 if (cs4231_chip->output_next_dma_handle) { cs4231_chip->output_next_dma_handle = 0; cs4231_chip->output_next_dma_size = 0; } -#endif + dcsr = readl(&(cs4231_chip->eb2p->dcsr)); + if(dcsr & EBUS_DCSR_EN_DMA) + writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2p->dcsr)); + + /* Else subsequent speed setting changes are ignored by the chip. */ + cs4231_disable_play(drv); } #endif @@ -1521,8 +1547,27 @@ cs4231_chip->output_next_dma_handle = 0; cs4231_chip->output_next_dma_size = 0; } +#if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */ + /* Else subsequent speed setting changes are ignored by the chip. */ + cs4231_disable_play(drv); +#endif } +#ifdef EB4231_SUPPORT +static void eb4231_pollinput(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int x = 0, dcsr; + + while (!((dcsr = readl(&(cs4231_chip->eb2c->dcsr))) & EBUS_DCSR_TC) && + x <= CS_TIMEOUT) { + x++; + } + + writel(dcsr | EBUS_DCSR_TC, &(cs4231_chip->eb2c->dcsr)); +} +#endif + static void cs4231_pollinput(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; @@ -1687,8 +1732,8 @@ { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - cs4231_chip->regs->iar = 0x0d; - cs4231_chip->regs->idr = (value ? LOOPB_ON : 0); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d); + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (value ? LOOPB_ON : 0)); } static int cs4231_ioctl(struct inode * inode, struct file * file, @@ -1716,61 +1761,15 @@ { struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int dummy1, dummy2; + int dummy; - printk("in eb4231_interrupt\n"); - - /* Clear the interrupt. */ - dummy1 = readl(&cs4231_chip->eb2p->dcsr); - dummy2 = readl(&cs4231_chip->eb2c->dcsr); + /* Read status. */ + dummy = readl(&cs4231_chip->eb2c->dcsr); - printk("play csr 0x%x capt csr 0x%x\n", dummy1, dummy2); - - cs4231_chip->eb2p->dcsr = dummy1; - cs4231_chip->eb2c->dcsr = dummy2; -#if 0 - if (dummy & APC_PLAY_INT) { - if (dummy & APC_XINT_PNVA) { - cs4231_chip->perchip_info.play.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), - cs4231_chip->playlen); - eb4231_playintr(drv); - } - /* Any other conditions we need worry about? */ - } - - if (dummy & APC_CAPT_INT) { - if (dummy & APC_XINT_CNVA) { - cs4231_chip->perchip_info.record.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), - cs4231_chip->reclen); - eb4231_recintr(drv); - } - /* Any other conditions we need worry about? */ - } - - - if (dummy & APC_XINT_CEMP) { - if (cs4231_chip->perchip_info.record.active == 0) { - /* Fix me */ - cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->perchip_info.record.error = 1; - eb4231_recintr(drv); - } - } - - if (dummy & APC_XINT_EMPT) { - if (!cs4231_chip->output_next_dma_handle) { - cs4231_chip->regs->dmacsr |= (APC_PPAUSE); - cs4231_disable_play(drv); - cs4231_chip->perchip_info.play.error = 1; - } - cs4231_chip->perchip_info.play.active = 0; - eb4231_playintr(drv); - - eb4231_getsamplecount(drv, cs4231_chip->playlen, 0); - } -#endif + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + eb4231_recintr(drv); } /* ebus audio play interrupt handler. */ @@ -1780,42 +1779,29 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; unsigned int dummy; - dprintk(("in eb4231_interrupt2\n")); - - /* Clear the interrupt. */ - dummy = readl(&cs4231_chip->eb2p->dcsr); - dprintk(("play csr 0x%x\n", dummy)); + /* Clear the interrupt. Bleh, when not using the next-address + * feature, TC can only be cleared by a reset. + */ + dummy = readl(&(cs4231_chip->eb2p->dcsr)); + writel(dummy, &(cs4231_chip->eb2p->dcsr)); - if (dummy & EBUS_DCSR_INT_PEND) { -#if 0 - if (!(dummy & EBUS_DCSR_NA_LOADED)) { -#endif - cs4231_chip->perchip_info.play.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), - cs4231_chip->playlen); - eb4231_playintr(drv); -#if 0 - } -#endif + /* If we get a terminal count and address loaded condition, + * this means the DNAR was copied into DACR. + */ + if((dummy & EBUS_DCSR_TC) != 0 + /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { + cs4231_chip->perchip_info.play.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), + cs4231_chip->playlen); + eb4231_playintr(drv); } - if (!(dummy & EBUS_DCSR_A_LOADED)) { -#if 0 - if (!cs4231_chip->output_next_dma_handle) { -#endif - writel((dummy & ~EBUS_DCSR_EN_DMA), &cs4231_chip->eb2p->dcsr); - cs4231_disable_play(drv); - cs4231_chip->perchip_info.play.error = 1; -#if 0 - } -#endif + if((dummy & EBUS_DCSR_A_LOADED) == 0) { cs4231_chip->perchip_info.play.active = 0; -#if 0 eb4231_playintr(drv); -#endif + eb4231_getsamplecount(drv, cs4231_chip->playlen, 0); } - } #endif @@ -2151,26 +2137,6 @@ nregs = len / sizeof(regs[0]); - /* Make sure we can map the registers first */ - if (check_region(edev->base_address[0], - sizeof(struct cs4231_regs))) { - printk("eb4231_attach: can't get region at %016lx\n", - edev->base_address[0]); - goto cleanup; - } - if (check_region(edev->base_address[1], - sizeof(struct linux_ebus_dma))) { - printk("eb4231_attach: can't get region at %016lx\n", - edev->base_address[1]); - goto cleanup; - } - if (check_region(edev->base_address[2], - sizeof(struct linux_ebus_dma))) { - printk("eb4231_attach: can't get region at %016lx\n", - edev->base_address[2]); - goto cleanup; - } - cs4231_chip->regs = (struct cs4231_regs *)edev->base_address[0]; cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->base_address[1]; cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->base_address[2]; @@ -2188,13 +2154,9 @@ cs4231_chip->irq = edev->irqs[0]; cs4231_chip->irq2 = edev->irqs[1]; - request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv); -#if 0 - enable_irq(cs4231_chip->irq); -#endif - - request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv); - enable_irq(cs4231_chip->irq2); + if(request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv) || + request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv)) + goto bail; cs4231_chip->nirqs = 2; @@ -2207,21 +2169,20 @@ err = register_sparcaudio_driver(drv, 1); if (err < 0) { + bail: printk(KERN_ERR "cs4231: unable to register\n"); cs4231_disable_interrupts(drv); disable_irq(cs4231_chip->irq); free_irq(cs4231_chip->irq, drv); - if (cs4231_chip->nirqs == 2) { - disable_irq(cs4231_chip->irq2); - free_irq(cs4231_chip->irq2, drv); - } + disable_irq(cs4231_chip->irq2); + free_irq(cs4231_chip->irq2, drv); + release_region((unsigned long)cs4231_chip->regs, sizeof(struct cs4231_regs)); release_region((unsigned long)cs4231_chip->eb2c, sizeof(struct linux_ebus_dma)); release_region((unsigned long)cs4231_chip->eb2p, sizeof(struct linux_ebus_dma)); - cleanup: kfree(drv->private); return -EIO; } @@ -2312,9 +2273,11 @@ sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size); } else { #ifdef EB4231_SUPPORT - release_region(cs4231_chip->regs, sizeof(struct cs4231_regs)); - release_region(cs4231_chip->eb2c, sizeof(struct linux_ebus_dma)); - release_region(cs4231_chip->eb2p, sizeof(struct linux_ebus_dma)); + disable_irq(cs4231_chip->irq2); + free_irq(cs4231_chip->irq2, drv); + release_region((unsigned long)cs4231_chip->regs, sizeof(struct cs4231_regs)); + release_region((unsigned long)cs4231_chip->eb2c, sizeof(struct linux_ebus_dma)); + release_region((unsigned long)cs4231_chip->eb2p, sizeof(struct linux_ebus_dma)); #endif } kfree(drv->private); diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h --- v2.2.6/linux/drivers/sbus/audio/cs4231.h Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/audio/cs4231.h Thu Apr 22 19:24:51 1999 @@ -64,6 +64,27 @@ volatile unsigned long recording_count; }; +#ifdef EB4231_SUPPORT +#define CS4231_READ32(__C, __REG) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? readl((unsigned long)(__REG)) : (*(__REG))) +#define CS4231_READ8(__C, __REG) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? readb((unsigned long)(__REG)) : (*(__REG))) +#define CS4231_WRITE32(__C, __REG, __VAL) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + writel((__VAL), (unsigned long)(__REG)) : \ + (*(__REG) = (__VAL))) +#define CS4231_WRITE8(__C, __REG, __VAL) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + writeb((__VAL), (unsigned long)(__REG)) : \ + (*(__REG) = (__VAL))) +#else +/* We can assume all is SBUS in this case. */ +#define CS4231_READ32(__C, __REG) (*(__REG)) +#define CS4231_READ8(__C, __REG) (*(__REG)) +#define CS4231_WRITE32(__C, __REG, __VAL) (*(__REG) = (__VAL)) +#define CS4231_WRITE8(__C, __REG, __VAL) (*(__REG) = (__VAL)) +#endif + /* Local status bits */ #define CS_STATUS_NEED_INIT 0x01 #define CS_STATUS_INIT_ON_CLOSE 0x02 diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.2.6/linux/drivers/sbus/char/pcikbd.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/char/pcikbd.c Wed Apr 28 08:47:39 1999 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.25 1999/02/08 07:01:48 ecd Exp $ +/* $Id: pcikbd.c,v 1.26 1999/04/28 11:55:42 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -228,8 +228,6 @@ "\r\000/"; /* 0x60 - 0x6f */ #endif -static unsigned int prev_scancode = 0; - int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode) { if(scancode < SC_LIM || scancode > 255 || keycode > 127) @@ -262,29 +260,22 @@ return 0; } } - if(scancode == 0) { - prev_scancode = 0; - return 0; - } return 1; } -int pcikbd_pretranslate(unsigned char scancode, char raw_mode) +int pcikbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) { - if(scancode == 0xff) { - prev_scancode = 0; + static int prev_scancode = 0; + + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; return 0; } - if(scancode == 0xe0 || scancode == 0xe1) { - prev_scancode = scancode; + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; return 0; } - return 1; -} - -int pcikbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) -{ if(prev_scancode) { if(prev_scancode != 0xe0) { if(prev_scancode == 0xe1 && scancode == 0x1d) { @@ -338,7 +329,7 @@ break; scancode = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG); if((status & KBD_STAT_OBF) && do_acknowledge(scancode)) - handle_scancode(scancode); + handle_scancode(scancode, !(scancode & 0x80)); status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG); } while(status & KBD_STAT_OBF); mark_bh(KEYBOARD_BH); diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.2.6/linux/drivers/sbus/char/sunkbd.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/char/sunkbd.c Thu Apr 22 19:24:51 1999 @@ -1479,7 +1479,7 @@ return 0; if (kbd_redirected) - kbd_table [kbd_opened-1].kbdmode = VC_XLATE; + kbd_table [kbd_redirected-1].kbdmode = VC_XLATE; kbd_redirected = 0; kbd_opened = 0; diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c --- v2.2.6/linux/drivers/sbus/char/sunmouse.c Mon Oct 5 13:13:40 1998 +++ linux/drivers/sbus/char/sunmouse.c Thu Apr 22 19:24:51 1999 @@ -94,7 +94,7 @@ #undef SMOUSE_DEBUG -static void +static int push_event (Firm_event *ev) { int next = (sunmouse.head + 1) % EV_SIZE; @@ -102,7 +102,9 @@ if (next != sunmouse.tail){ sunmouse.queue.ev [sunmouse.head] = *ev; sunmouse.head = next; + return 1; } + return 0; } static int @@ -150,7 +152,11 @@ extern void rs_change_mouse_baud(int newbaud); if(mouse_baud == 1200) + mouse_baud = 2400; + else if(mouse_baud == 2400) mouse_baud = 4800; + else if(mouse_baud == 4800) + mouse_baud = 9600; else mouse_baud = 1200; @@ -196,7 +202,7 @@ sun_mouse_inbyte(unsigned char byte) { signed char mvalue; - int d; + int d, pushed = 0; Firm_event ev; add_mouse_randomness (byte); @@ -290,29 +296,31 @@ } ev.time = xtime; ev.value = ev.value ? VKEY_DOWN : VKEY_UP; - push_event (&ev); + pushed += push_event (&ev); } if (sunmouse.delta_x){ ev.id = LOC_X_DELTA; ev.time = xtime; ev.value = sunmouse.delta_x; - push_event (&ev); + pushed += push_event (&ev); sunmouse.delta_x = 0; } if (sunmouse.delta_y){ ev.id = LOC_Y_DELTA; ev.time = xtime; ev.value = sunmouse.delta_y; - push_event (&ev); + pushed += push_event (&ev); } - /* We just completed a transaction, wake up whoever is awaiting - * this event. - */ - sunmouse.ready = 1; - if (sunmouse.fasync) - kill_fasync (sunmouse.fasync, SIGIO); - wake_up_interruptible(&sunmouse.proc_list); + if(pushed != 0) { + /* We just completed a transaction, wake up whoever is awaiting + * this event. + */ + sunmouse.ready = 1; + if (sunmouse.fasync) + kill_fasync (sunmouse.fasync, SIGIO); + wake_up_interruptible(&sunmouse.proc_list); + } return; } diff -u --recursive --new-file v2.2.6/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.2.6/linux/drivers/sbus/char/zs.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/sbus/char/zs.c Thu Apr 22 19:24:51 1999 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.40 1999/02/23 15:14:45 jj Exp $ +/* $Id: zs.c,v 1.41 1999/04/16 16:22:27 jj Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1844,7 +1844,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.40 $"; + char *revision = "$Revision: 1.41 $"; char *version, *p; version = strchr(revision, ' '); @@ -2276,11 +2276,6 @@ #if CONFIG_AP1000 printk("not doing zs_init()\n"); return 0; -#endif - -#ifdef CONFIG_PCI - if (pci_present()) - return 0; #endif /* Setup base handler, and timer table. */ diff -u --recursive --new-file v2.2.6/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- v2.2.6/linux/drivers/scsi/ide-scsi.c Tue Feb 23 15:21:33 1999 +++ linux/drivers/scsi/ide-scsi.c Thu Apr 22 19:24:50 1999 @@ -67,7 +67,7 @@ int b_count; /* Bytes transferred from current entry */ Scsi_Cmnd *scsi_cmd; /* SCSI command */ void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ - unsigned int flags; /* Status/Action flags */ + unsigned long flags; /* Status/Action flags */ unsigned long timeout; /* Command timeout */ } idescsi_pc_t; @@ -92,9 +92,9 @@ typedef struct { ide_drive_t *drive; idescsi_pc_t *pc; /* Current packet command */ - unsigned int flags; /* Status/Action flags */ - int transform; /* SCSI cmd translation layer */ - int log; /* log flags */ + unsigned long flags; /* Status/Action flags */ + unsigned long transform; /* SCSI cmd translation layer */ + unsigned long log; /* log flags */ } idescsi_scsi_t; /* diff -u --recursive --new-file v2.2.6/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.2.6/linux/drivers/scsi/qlogicisp.c Fri Nov 27 13:09:24 1998 +++ linux/drivers/scsi/qlogicisp.c Thu Apr 22 19:30:08 1999 @@ -27,6 +27,7 @@ #include #include #include +#include #include "sd.h" #include "hosts.h" @@ -49,7 +50,7 @@ /* Macros used for debugging */ #define DEBUG_ISP1020 0 -#define DEBUG_ISP1020_INT 0 +#define DEBUG_ISP1020_INTR 0 #define DEBUG_ISP1020_SETUP 0 #define TRACE_ISP 0 @@ -730,17 +731,17 @@ cmd->hdr.entry_type = ENTRY_COMMAND; cmd->hdr.entry_cnt = 1; - cmd->handle = (u_int) virt_to_bus(Cmnd); + cmd->handle = cpu_to_le32((u_int) virt_to_bus(Cmnd)); cmd->target_lun = Cmnd->lun; cmd->target_id = Cmnd->target; - cmd->cdb_length = Cmnd->cmd_len; - cmd->control_flags = CFLAG_READ | CFLAG_WRITE; - cmd->time_out = 30; + cmd->cdb_length = cpu_to_le16(Cmnd->cmd_len); + cmd->control_flags = cpu_to_le16(CFLAG_READ | CFLAG_WRITE); + cmd->time_out = cpu_to_le16(30); memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); if (Cmnd->use_sg) { - cmd->segment_cnt = sg_count = Cmnd->use_sg; + cmd->segment_cnt = cpu_to_le16(sg_count = Cmnd->use_sg); sg = (struct scatterlist *) Cmnd->request_buffer; ds = cmd->dataseg; @@ -749,8 +750,8 @@ if (n > 4) n = 4; for (i = 0; i < n; i++) { - ds[i].d_base = (u_int) virt_to_bus(sg->address); - ds[i].d_count = sg->length; + ds[i].d_base = cpu_to_le32((u_int) virt_to_bus(sg->address)); + ds[i].d_count = cpu_to_le32(sg->length); ++sg; } sg_count -= 4; @@ -776,18 +777,18 @@ if (n > 7) n = 7; for (i = 0; i < n; ++i) { - ds[i].d_base = (u_int)virt_to_bus(sg->address); - ds[i].d_count = sg->length; + ds[i].d_base = cpu_to_le32((u_int)virt_to_bus(sg->address)); + ds[i].d_count = cpu_to_le32(sg->length); ++sg; } sg_count -= n; } } else { cmd->dataseg[0].d_base = - (u_int) virt_to_bus(Cmnd->request_buffer); + cpu_to_le32((u_int) virt_to_bus(Cmnd->request_buffer)); cmd->dataseg[0].d_count = - (u_int) Cmnd->request_bufflen; - cmd->segment_cnt = 1; + cpu_to_le32((u_int) Cmnd->request_bufflen); + cmd->segment_cnt = cpu_to_le16(1); } outw(in_ptr, host->io_port + MBOX4); @@ -861,22 +862,22 @@ DEBUG_INTR(printk("qlogicisp : response queue update\n")); DEBUG_INTR(printk("qlogicisp : response queue depth %d\n", - QUEUE_DEPTH(in_ptr, out_ptr))); + QUEUE_DEPTH(in_ptr, out_ptr, RES_QUEUE_LEN))); while (out_ptr != in_ptr) { sts = (struct Status_Entry *) &hostdata->res[out_ptr][0]; out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; - Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle); + Cmnd = (Scsi_Cmnd *) bus_to_virt(le32_to_cpu(sts->handle)); TRACE("done", out_ptr, Cmnd); - if (sts->completion_status == CS_RESET_OCCURRED - || sts->completion_status == CS_ABORTED - || (sts->status_flags & STF_BUS_RESET)) + if (le16_to_cpu(sts->completion_status) == CS_RESET_OCCURRED + || le16_to_cpu(sts->completion_status) == CS_ABORTED + || (le16_to_cpu(sts->status_flags) & STF_BUS_RESET)) hostdata->send_marker = 1; - if (sts->state_flags & SF_GOT_SENSE) + if (le16_to_cpu(sts->state_flags) & SF_GOT_SENSE) memcpy(Cmnd->sense_buffer, sts->req_sense_data, sizeof(Cmnd->sense_buffer)); @@ -917,24 +918,24 @@ ENTER("isp1020_return_status"); DEBUG(printk("qlogicisp : completion status = 0x%04x\n", - sts->completion_status)); + le16_to_cpu(sts->completion_status))); - switch(sts->completion_status) { + switch(le16_to_cpu(sts->completion_status)) { case CS_COMPLETE: host_status = DID_OK; break; case CS_INCOMPLETE: - if (!(sts->state_flags & SF_GOT_BUS)) + if (!(le16_to_cpu(sts->state_flags) & SF_GOT_BUS)) host_status = DID_NO_CONNECT; - else if (!(sts->state_flags & SF_GOT_TARGET)) + else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_TARGET)) host_status = DID_BAD_TARGET; - else if (!(sts->state_flags & SF_SENT_CDB)) + else if (!(le16_to_cpu(sts->state_flags) & SF_SENT_CDB)) host_status = DID_ERROR; - else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) + else if (!(le16_to_cpu(sts->state_flags) & SF_TRANSFERRED_DATA)) host_status = DID_ERROR; - else if (!(sts->state_flags & SF_GOT_STATUS)) + else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_STATUS)) host_status = DID_ERROR; - else if (!(sts->state_flags & SF_GOT_SENSE)) + else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_SENSE)) host_status = DID_ERROR; break; case CS_DMA_ERROR: @@ -970,17 +971,17 @@ break; default: printk("qlogicisp : unknown completion status 0x%04x\n", - sts->completion_status); + le16_to_cpu(sts->completion_status)); host_status = DID_ERROR; break; } DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n", - reason[host_status], sts->scsi_status)); + reason[host_status], le16_to_cpu(sts->scsi_status))); LEAVE("isp1020_return_status"); - return (sts->scsi_status & STATUS_MASK) | (host_status << 16); + return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16); } @@ -1082,7 +1083,9 @@ ENTER("isp1020_reset_hardware"); outw(ISP_RESET, host->io_port + PCI_INTF_CTL); + udelay(100); outw(HCCR_RESET, host->io_port + HOST_HCCR); + udelay(100); outw(HCCR_RELEASE, host->io_port + HOST_HCCR); outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR); @@ -1103,27 +1106,25 @@ printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5)); #endif /* DEBUG_ISP1020 */ + param[0] = MBOX_NO_OP; + isp1020_mbox_command(host, param); + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicisp : NOP test failed\n"); + return 1; + } + DEBUG(printk("qlogicisp : loading risc ram\n")); #if RELOAD_FIRMWARE - /* Do not reload firmware if 1040B, i.e. revision 5 chip. */ - if (((struct isp1020_hostdata *) host->hostdata)->revision >= 5) - printk("qlogicisp : 1040B or later chip," - " firmware not (re)loaded\n"); - else - { - int i; - for (i = 0; i < risc_code_length01; i++) { - param[0] = MBOX_WRITE_RAM_WORD; - param[1] = risc_code_addr01 + i; - param[2] = risc_code01[i]; - - isp1020_mbox_command(host, param); - - if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicisp : firmware load failure\n"); - return 1; - } + for (loop_count = 0; loop_count < risc_code_length01; loop_count++) { + param[0] = MBOX_WRITE_RAM_WORD; + param[1] = risc_code_addr01 + loop_count; + param[2] = risc_code01[loop_count]; + isp1020_mbox_command(host, param); + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicisp : firmware load failure at %d\n", + loop_count); + return 1; } } #endif /* RELOAD_FIRMWARE */ @@ -1200,6 +1201,15 @@ return 1; } +#ifdef __sparc__ + command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY| + PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR); + pci_write_config_word(pdev, PCI_COMMAND, command); + pci_read_config_word(pdev, PCI_COMMAND, &command); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 16); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); +#endif + if (command & PCI_COMMAND_IO && (io_base & 3) == 1) io_base &= PCI_BASE_ADDRESS_IO_MASK; else { @@ -1227,6 +1237,8 @@ sh->irq = irq; sh->io_port = io_base; + sh->max_id = MAX_TARGETS; + sh->max_lun = MAX_LUNS; LEAVE("isp1020_init"); @@ -1691,14 +1703,15 @@ printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags); printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n", - status->scsi_status, status->completion_status); + le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status)); printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n", - status->state_flags, status->status_flags); + le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags)); printk("qlogicisp : time = 0x%04x, request sense length = 0x%04x\n", - status->time, status->req_sense_len); - printk("qlogicisp : residual transfer length = 0x%08x\n", status->residual); + le16_to_cpu(status->time), le16_to_cpu(status->req_sense_len)); + printk("qlogicisp : residual transfer length = 0x%08x\n", + le32_to_cpu(status->residual)); - for (i = 0; i < status->req_sense_len; i++) + for (i = 0; i < le16_to_cpu(status->req_sense_len); i++) printk("qlogicisp : sense data = 0x%02x\n", status->req_sense_data[i]); } diff -u --recursive --new-file v2.2.6/linux/drivers/scsi/qlogicisp_asm.c linux/drivers/scsi/qlogicisp_asm.c --- v2.2.6/linux/drivers/scsi/qlogicisp_asm.c Sun Feb 2 05:34:32 1997 +++ linux/drivers/scsi/qlogicisp_asm.c Thu Apr 22 19:30:08 1999 @@ -1,1304 +1,2034 @@ /* - * Version 2.10 Initiator Firmware (16:13 Oct 18, 1995) + * Firmware Version 7.63.00 (12:07 Jan 27, 1999) */ - -static const unsigned short risc_code_version = 2*1024+10; +static const unsigned short risc_code_version = 7*1024+63; static const unsigned short risc_code_addr01 = 0x1000 ; #if RELOAD_FIRMWARE -static const unsigned short risc_code01[] = { - 0x0078, 0x1041, 0x0000, 0x283a, 0x0000, 0x2043, 0x4f50, 0x5952, - 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, - 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320, - 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350, - 0x3130, 0x3230, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, - 0x6572, 0x7369, 0x6f6e, 0x2030, 0x322e, 0x3130, 0x2020, 0x2043, - 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050, - 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020, - 0x2400, 0x20b9, 0x1212, 0x2071, 0x0010, 0x70c3, 0x0004, 0x20c9, - 0x43ff, 0x2089, 0x115b, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, - 0x2020, 0x70d3, 0x0002, 0x3f00, 0x70d6, 0x20c1, 0x0008, 0x2019, - 0x0000, 0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff, - 0x2d64, 0x206b, 0x0a0a, 0xaddc, 0x3fff, 0x2b54, 0x205b, 0x5050, - 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10b3, 0xa386, 0x000f, 0x0040, - 0x1079, 0x2c6a, 0x2a5a, 0x20c1, 0x0000, 0x2019, 0x000f, 0x0078, - 0x1059, 0x2c6a, 0x2a5a, 0x20c1, 0x0008, 0x2009, 0x7fff, 0x2148, - 0x2944, 0x204b, 0x0a0a, 0xa9bc, 0x3fff, 0x2734, 0x203b, 0x5050, - 0x2114, 0xa286, 0x0a0a, 0x0040, 0x109d, 0x284a, 0x263a, 0x20c1, - 0x0004, 0x2009, 0x3fff, 0x2134, 0x200b, 0x5050, 0x2114, 0xa286, - 0x5050, 0x0040, 0x109e, 0x0078, 0x1163, 0x284a, 0x263a, 0x98c0, - 0xa188, 0x1000, 0x212c, 0x200b, 0xa5a5, 0x2114, 0xa286, 0xa5a5, - 0x0040, 0x10b0, 0x250a, 0xa18a, 0x1000, 0x98c1, 0x0078, 0x10b5, - 0x250a, 0x0078, 0x10b5, 0x2c6a, 0x2a5a, 0x2130, 0xa18a, 0x0040, - 0x2128, 0xa1a2, 0x3900, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, - 0x8424, 0xa192, 0x4400, 0x2009, 0x0000, 0x2001, 0x002f, 0x1078, - 0x1a70, 0x2218, 0x2079, 0x3900, 0x2fa0, 0x2408, 0x2011, 0x0000, - 0x20a9, 0x0040, 0x42a4, 0x8109, 0x00c0, 0x10d0, 0x7eea, 0x7dde, - 0x8528, 0x7dda, 0x7ce2, 0x7be6, 0x787b, 0x0000, 0x2031, 0x0030, - 0x78c3, 0x0101, 0x780b, 0x0002, 0x780f, 0x0002, 0x784f, 0x0003, - 0x2069, 0x3940, 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, - 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, 0x6823, 0x0006, - 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3a00, 0x2011, 0x0020, - 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, 0x6803, 0xfd00, +static const unsigned short risc_code01[] = { + 0x0078, 0x103a, 0x0000, 0x3f14, 0x0000, 0x2043, 0x4f50, 0x5952, + 0x4947, 0x4854, 0x2031, 0x3939, 0x3520, 0x514c, 0x4f47, 0x4943, + 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, + 0x3130, 0x3230, 0x2049, 0x2f54, 0x2046, 0x6972, 0x6d77, 0x6172, + 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x372e, 0x3633, + 0x2020, 0x2043, 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, + 0x3030, 0x2050, 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, + 0x3031, 0x2024, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x0048, + 0x1045, 0x0038, 0x104b, 0x0078, 0x1047, 0x0028, 0x104b, 0x20b9, + 0x1212, 0x0078, 0x104d, 0x20b9, 0x2222, 0x20c1, 0x0008, 0x2071, + 0x0010, 0x70c3, 0x0004, 0x20c9, 0x76ff, 0x2089, 0x1186, 0x70c7, + 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0007, 0x3f00, + 0x70d6, 0x20c1, 0x0008, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100, + 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, 0x206b, 0x0a0a, 0xaddc, + 0x3fff, 0x2b54, 0x205b, 0x5050, 0x2114, 0xa286, 0xa5a5, 0x0040, + 0x10bf, 0xa386, 0x000f, 0x0040, 0x1085, 0x2c6a, 0x2a5a, 0x20c1, + 0x0000, 0x2019, 0x000f, 0x0078, 0x1065, 0x2c6a, 0x2a5a, 0x20c1, + 0x0008, 0x2009, 0x7fff, 0x2148, 0x2944, 0x204b, 0x0a0a, 0xa9bc, + 0x3fff, 0x2734, 0x203b, 0x5050, 0x2114, 0xa286, 0x0a0a, 0x0040, + 0x10a9, 0x284a, 0x263a, 0x20c1, 0x0004, 0x2009, 0x3fff, 0x2134, + 0x200b, 0x5050, 0x2114, 0xa286, 0x5050, 0x0040, 0x10aa, 0x0078, + 0x118e, 0x284a, 0x263a, 0x98c0, 0xa188, 0x1000, 0x212c, 0x200b, + 0xa5a5, 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10bc, 0x250a, 0xa18a, + 0x1000, 0x98c1, 0x0078, 0x10c1, 0x250a, 0x0078, 0x10c1, 0x2c6a, + 0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5000, 0x8424, + 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7700, 0x2009, + 0x0000, 0x2001, 0x0031, 0x1078, 0x1c9d, 0x2218, 0x2079, 0x5000, + 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109, + 0x00c0, 0x10dc, 0x7ef2, 0x8528, 0x7de6, 0x7cea, 0x7bee, 0x7883, + 0x0000, 0x2031, 0x0030, 0x78cf, 0x0101, 0x780b, 0x0002, 0x780f, + 0x0002, 0x784f, 0x0003, 0x2069, 0x5040, 0x2001, 0x04fd, 0x2004, + 0xa082, 0x0005, 0x0048, 0x1104, 0x0038, 0x1100, 0x0078, 0x1108, + 0x681b, 0x003c, 0x0078, 0x110a, 0x00a8, 0x1108, 0x681b, 0x003c, + 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008, + 0x6813, 0x0005, 0x6823, 0x0000, 0x6827, 0x0006, 0x6817, 0x0008, + 0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5280, 0x2011, 0x0020, + 0x2009, 0x0010, 0x680b, 0x080c, 0x680f, 0x0019, 0x6803, 0xfd00, 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, - 0x8109, 0x00c0, 0x1102, 0x2069, 0x3a80, 0x20a9, 0x0080, 0x680b, - 0x0040, 0x7be8, 0xa386, 0xfeff, 0x00c0, 0x1124, 0x6817, 0x0100, - 0x681f, 0x0064, 0x0078, 0x1128, 0x6817, 0x0064, 0x681f, 0x0002, - 0xade8, 0x0010, 0x0070, 0x112e, 0x0078, 0x1117, 0x1078, 0x1d15, - 0x1078, 0x3366, 0x1078, 0x18a4, 0x1078, 0x37fc, 0x3200, 0xa085, - 0x000d, 0x2090, 0x70c3, 0x0000, 0x0090, 0x1145, 0x70c0, 0xa086, - 0x0002, 0x00c0, 0x1145, 0x1078, 0x1274, 0x1078, 0x1186, 0x78c0, - 0xa005, 0x00c0, 0x1151, 0x1078, 0x1a99, 0x0068, 0x1155, 0x1078, - 0x1c6f, 0x0068, 0x1155, 0x1078, 0x1997, 0x00e0, 0x1145, 0x1078, - 0x369a, 0x0078, 0x1145, 0x1163, 0x1165, 0x1ebb, 0x1ebb, 0x33d7, - 0x33d7, 0x1ebb, 0x1ebb, 0x0078, 0x1163, 0x0078, 0x1165, 0x0078, - 0x1167, 0x0078, 0x1169, 0x2009, 0x0022, 0x2104, 0xa086, 0x4000, - 0x0040, 0x1181, 0x7008, 0x800b, 0x00c8, 0x1181, 0x7007, 0x0002, - 0xa08c, 0x0060, 0x00c0, 0x1182, 0xa084, 0x0008, 0x0040, 0x1181, - 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x1277, 0x0068, 0x11f1, - 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x11f1, 0x7814, - 0xa005, 0x00c0, 0x1197, 0x0010, 0x11f2, 0x0078, 0x11f1, 0x2009, - 0x3968, 0x2104, 0xa005, 0x00c0, 0x11f1, 0x2009, 0x3971, 0x200b, - 0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11bc, 0x7816, 0x2009, - 0x396f, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca, + 0x8109, 0x00c0, 0x1122, 0x2069, 0x5300, 0x2009, 0x0002, 0x20a9, + 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bf0, 0xa386, 0xfeff, + 0x00c0, 0x1148, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x114c, + 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x0070, 0x1152, + 0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x21e9, 0x1078, + 0x46e9, 0x1078, 0x1946, 0x1078, 0x4bdf, 0x3200, 0xa085, 0x000d, + 0x2090, 0x70c3, 0x0000, 0x0090, 0x116c, 0x70c0, 0xa086, 0x0002, + 0x00c0, 0x116c, 0x1078, 0x1284, 0x1078, 0x1196, 0x78cc, 0xa005, + 0x00c0, 0x117a, 0x1078, 0x1cc6, 0x0010, 0x1180, 0x0068, 0x1180, + 0x1078, 0x20c8, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1a2b, + 0x00e0, 0x116c, 0x1078, 0x4a66, 0x0078, 0x116c, 0x118e, 0x1190, + 0x23ea, 0x23ea, 0x476a, 0x476a, 0x23ea, 0x23ea, 0x0078, 0x118e, + 0x0078, 0x1190, 0x0078, 0x1192, 0x0078, 0x1194, 0x0068, 0x1201, + 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1201, 0x7814, + 0xa005, 0x00c0, 0x11a7, 0x0010, 0x1202, 0x0078, 0x1201, 0x2009, + 0x505b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5064, 0x200b, + 0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11cc, 0x7816, 0x2009, + 0x5062, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca, 0x611c, 0xa18c, 0xff00, 0x6020, 0xa084, 0x00ff, 0xa105, 0x70ce, - 0x1078, 0x1896, 0x0078, 0x11ef, 0x7814, 0xa086, 0x0018, 0x00c0, - 0x11c3, 0x1078, 0x1622, 0x7817, 0x0000, 0x2009, 0x396f, 0x2104, - 0xa065, 0x0040, 0x11df, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6, - 0x0c7f, 0x609f, 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6087, - 0x0103, 0x1078, 0x181d, 0x00c0, 0x11eb, 0x1078, 0x1896, 0x2009, - 0x396f, 0x200b, 0x0000, 0x2009, 0x3969, 0x2104, 0x200b, 0x0000, - 0xa005, 0x0040, 0x11ef, 0x2001, 0x4005, 0x0078, 0x1276, 0x0078, - 0x1274, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000, - 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1242, 0x2038, - 0x0079, 0x1202, 0x1274, 0x12cf, 0x1293, 0x12cf, 0x1338, 0x1338, - 0x128a, 0x16fd, 0x1343, 0x1282, 0x1297, 0x1299, 0x129b, 0x129d, - 0x1702, 0x1282, 0x1355, 0x1380, 0x163a, 0x16f7, 0x129f, 0x1569, - 0x158b, 0x15a1, 0x15be, 0x1526, 0x1534, 0x1548, 0x155c, 0x13f3, - 0x1282, 0x13a1, 0x13a7, 0x13ac, 0x13b1, 0x13b7, 0x13bc, 0x13c1, - 0x13c6, 0x13cb, 0x13cf, 0x13e4, 0x13f0, 0x1282, 0x1282, 0x1282, - 0x1282, 0x13ff, 0x1408, 0x1417, 0x143d, 0x1447, 0x144e, 0x1474, - 0x1483, 0x1492, 0x14a4, 0x1506, 0x1516, 0x1282, 0x1282, 0x1282, - 0x1282, 0x151b, 0xa0bc, 0xffa0, 0x00c0, 0x1282, 0x2038, 0xa084, - 0x001f, 0x0079, 0x124b, 0x1719, 0x171c, 0x172c, 0x17a8, 0x17e1, - 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, - 0x1282, 0x1282, 0x1282, 0x12c5, 0x132e, 0x134b, 0x1376, 0x1630, - 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x17f9, 0x1803, 0x1807, - 0x1815, 0x1282, 0x1282, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, - 0x1276, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, - 0x1277, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, - 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x1277, 0x70c3, 0x4006, - 0x0078, 0x1277, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, - 0x53a3, 0x0078, 0x1274, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, - 0x1274, 0x0078, 0x1274, 0x0078, 0x1274, 0x0078, 0x1274, 0x2091, - 0x8000, 0x70c3, 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, - 0x2020, 0x70d3, 0x0002, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, - 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, - 0x0470, 0x2061, 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, - 0x5000, 0x2091, 0x4080, 0x0078, 0x0455, 0x1078, 0x1a04, 0x00c0, - 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x12d2, 0x2029, - 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2098, - 0x2031, 0x0030, 0x81ff, 0x0040, 0x1274, 0x7007, 0x0004, 0x731a, - 0x721e, 0x7422, 0x7526, 0x2051, 0x0012, 0x2049, 0x130d, 0x2041, - 0x1274, 0x7003, 0x0002, 0xa786, 0x0001, 0x0040, 0x12f5, 0xa786, - 0x0050, 0x0040, 0x12f5, 0x0078, 0x12fb, 0x2049, 0x131a, 0x2041, - 0x1326, 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, 0x00c8, - 0x1303, 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, 0x0040, - 0x131a, 0xa786, 0x0050, 0x0040, 0x131a, 0x700c, 0xa084, 0x007f, - 0x2009, 0x0040, 0xa102, 0x8004, 0x094a, 0x20a8, 0x26a0, 0x53a6, - 0x0078, 0x116b, 0x700c, 0xa084, 0x007f, 0x0040, 0x131a, 0x80ac, - 0x0048, 0x131a, 0x2698, 0x53a5, 0x0078, 0x116b, 0x700c, 0xa084, - 0x007f, 0x80ac, 0x2698, 0x53a5, 0x0078, 0x1274, 0x1078, 0x1a04, - 0x00c0, 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x12d2, - 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1340, 0x200a, - 0x72ca, 0x0078, 0x1273, 0x70c7, 0x0002, 0x70cb, 0x000a, 0x70cf, - 0x0000, 0x0078, 0x1274, 0x1078, 0x1a04, 0x00c0, 0x1286, 0x75d8, - 0x76dc, 0x75da, 0x76de, 0x0078, 0x1358, 0x2029, 0x0000, 0x2530, - 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, - 0xa005, 0x0040, 0x1370, 0x8001, 0x788a, 0x7a92, 0x7b96, 0x7d9a, - 0x7e9e, 0x7c8e, 0x78c0, 0xa084, 0xfffc, 0x78c2, 0x0078, 0x1374, - 0x78c0, 0xa085, 0x0001, 0x78c2, 0x0078, 0x1274, 0x1078, 0x1a04, - 0x00c0, 0x1286, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1383, + 0x1078, 0x192b, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0, + 0x11d3, 0x1078, 0x165a, 0x7817, 0x0000, 0x2009, 0x5062, 0x2104, + 0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1996, + 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c, 0x6007, + 0x0103, 0x1078, 0x1907, 0x00c0, 0x11fb, 0x1078, 0x192b, 0x2009, + 0x5062, 0x200b, 0x0000, 0x2009, 0x505c, 0x2104, 0x200b, 0x0000, + 0xa005, 0x0040, 0x11ff, 0x2001, 0x4005, 0x0078, 0x1286, 0x0078, + 0x1284, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000, + 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1252, 0x2038, + 0x0079, 0x1212, 0x1284, 0x12e5, 0x12a9, 0x12fe, 0x130d, 0x1313, + 0x12a0, 0x1748, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3, + 0x174d, 0x1298, 0x1329, 0x1360, 0x1672, 0x1742, 0x12b5, 0x1591, + 0x15ad, 0x15c9, 0x15f4, 0x154a, 0x1558, 0x156c, 0x1580, 0x13df, + 0x1298, 0x138d, 0x1393, 0x1398, 0x139d, 0x13a3, 0x13a8, 0x13ad, + 0x13b2, 0x13b7, 0x13bb, 0x13d0, 0x13dc, 0x1298, 0x1298, 0x1298, + 0x1298, 0x13eb, 0x13f4, 0x1403, 0x1429, 0x1433, 0x143a, 0x1480, + 0x148f, 0x149e, 0x14b0, 0x152a, 0x153a, 0x1298, 0x1298, 0x1298, + 0x1298, 0x153f, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084, + 0x001f, 0x0079, 0x125b, 0x1786, 0x1789, 0x1799, 0x1298, 0x1298, + 0x18d8, 0x18f5, 0x1298, 0x1298, 0x1298, 0x18f9, 0x1901, 0x1298, + 0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x1356, 0x1668, + 0x1764, 0x1778, 0x1298, 0x1829, 0x1298, 0x18b4, 0x18be, 0x18c2, + 0x18d0, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, + 0x1286, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, + 0x1287, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x00e0, + 0x128f, 0x00e0, 0x1291, 0x0068, 0x1291, 0x2091, 0x4080, 0x007c, + 0x70c3, 0x4001, 0x0078, 0x1287, 0x70c3, 0x4006, 0x0078, 0x1287, + 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, + 0x1284, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x1284, 0x0078, + 0x1284, 0x0078, 0x1284, 0x0078, 0x1284, 0x2091, 0x8000, 0x70c3, + 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, + 0x0007, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, + 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061, + 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091, + 0x4080, 0x0078, 0x0455, 0x1078, 0x1b36, 0x00c0, 0x129c, 0x75d8, + 0x74dc, 0x75da, 0x74de, 0x0078, 0x12e8, 0x2029, 0x0000, 0x2520, + 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1a70, 0x0040, 0x1284, + 0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1b36, 0x00c0, 0x129c, + 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1301, 0x2029, 0x0000, + 0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1ad0, 0x0040, + 0x1284, 0x70c3, 0x4002, 0x0078, 0x1284, 0x71c4, 0x70c8, 0x2114, + 0x200a, 0x0078, 0x1282, 0x71c4, 0x2114, 0x0078, 0x1282, 0x70c7, + 0x0007, 0x70cb, 0x003f, 0x70cf, 0x0000, 0x0078, 0x1284, 0x1078, + 0x1b36, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, + 0x132c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, + 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1350, 0x8001, + 0x7892, 0xa084, 0xfc00, 0x0040, 0x1345, 0x78cc, 0xa085, 0x0001, + 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2, + 0x7ea6, 0x7c96, 0x78cc, 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1354, + 0x78cc, 0xa085, 0x0001, 0x78ce, 0x0078, 0x1284, 0x1078, 0x1b36, + 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1363, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, - 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x139b, 0x8001, 0x78a6, - 0x7aae, 0x7bb2, 0x7db6, 0x7eba, 0x7caa, 0x78c0, 0xa084, 0xfcff, - 0x78c2, 0x0078, 0x139f, 0x78c0, 0xa085, 0x0100, 0x78c2, 0x0078, - 0x1274, 0x2009, 0x395f, 0x210c, 0x7ae4, 0x0078, 0x1272, 0x2009, - 0x3941, 0x210c, 0x0078, 0x1273, 0x2009, 0x3942, 0x210c, 0x0078, - 0x1273, 0x2061, 0x3940, 0x610c, 0x6210, 0x0078, 0x1272, 0x2009, - 0x3945, 0x210c, 0x0078, 0x1273, 0x2009, 0x3946, 0x210c, 0x0078, - 0x1273, 0x2009, 0x3947, 0x210c, 0x0078, 0x1273, 0x2009, 0x3948, - 0x210c, 0x0078, 0x1273, 0x7908, 0x7a0c, 0x0078, 0x1272, 0x71c4, - 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3a00, - 0x6a00, 0x6804, 0xa084, 0x0008, 0x0040, 0x13e1, 0x6b08, 0x0078, - 0x13e2, 0x6b0c, 0x0078, 0x1271, 0x77c4, 0x1078, 0x18b4, 0x2091, - 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x1271, - 0x794c, 0x0078, 0x1273, 0x77c4, 0x1078, 0x18b4, 0x2091, 0x8000, - 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, 0x1271, 0x71c4, - 0xa182, 0x0010, 0x00c8, 0x126c, 0x1078, 0x1d9b, 0x0078, 0x1271, - 0x71c4, 0xa182, 0x0010, 0x00c8, 0x126c, 0x2011, 0x3941, 0x2204, - 0x007e, 0x2112, 0x1078, 0x1d54, 0x017f, 0x0078, 0x1273, 0x71c4, - 0x2011, 0x1435, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x1427, - 0x8210, 0x0070, 0x1425, 0x0078, 0x141c, 0x0078, 0x126c, 0xa292, - 0x1435, 0x027e, 0x2011, 0x3942, 0x2204, 0x2112, 0x017f, 0x007e, - 0x1078, 0x1d60, 0x017f, 0x0078, 0x1273, 0x03e8, 0x00fa, 0x01f4, - 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x3940, 0x610c, - 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, 0x1272, 0x2061, - 0x3940, 0x6114, 0x70c4, 0x6016, 0x0078, 0x1273, 0x71c4, 0x2011, - 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1467, 0x2011, - 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, 0x1467, 0x2011, - 0x0006, 0x2019, 0x2323, 0xa186, 0x003c, 0x00c0, 0x126c, 0x2061, - 0x3940, 0x6018, 0x007e, 0x611a, 0x23b8, 0x1078, 0x1d71, 0x1078, - 0x37fc, 0x017f, 0x0078, 0x1273, 0x71c4, 0xa184, 0xffcf, 0x00c0, - 0x126c, 0x2011, 0x3947, 0x2204, 0x2112, 0x007e, 0x1078, 0x1d93, - 0x017f, 0x0078, 0x1273, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x126c, - 0x2011, 0x3948, 0x2204, 0x007e, 0x2112, 0x1078, 0x1d82, 0x017f, - 0x0078, 0x1273, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x126b, - 0xa284, 0xfffd, 0x00c0, 0x126b, 0x2100, 0x7908, 0x780a, 0x2200, - 0x7a0c, 0x780e, 0x0078, 0x1272, 0x71c4, 0x8107, 0xa084, 0x000f, - 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3a00, 0x2019, 0x0000, 0x72c8, - 0x6800, 0x007e, 0xa226, 0x0040, 0x14d3, 0x6a02, 0xa484, 0x2000, - 0x0040, 0x14bc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14c2, - 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14d3, 0x810f, 0xa284, - 0x4000, 0x0040, 0x14cf, 0x1078, 0x1db5, 0x0078, 0x14d3, 0x1078, - 0x1da7, 0x0078, 0x14d3, 0x72cc, 0x82ff, 0x0040, 0x14ff, 0x6808, - 0xa206, 0x0040, 0x14ff, 0xa2a4, 0x00ff, 0x2061, 0x3940, 0x6118, - 0xa186, 0x0028, 0x0040, 0x14ec, 0xa186, 0x0032, 0x0040, 0x14f2, - 0xa186, 0x003c, 0x0040, 0x14f8, 0xa482, 0x0064, 0x00c8, 0x126d, - 0x0078, 0x14fc, 0xa482, 0x0050, 0x00c8, 0x126d, 0x0078, 0x14fc, - 0xa482, 0x0043, 0x00c8, 0x126d, 0x6a0a, 0xa39d, 0x000a, 0x6804, - 0xa305, 0x6806, 0x027f, 0x6b0c, 0x0078, 0x1271, 0x77c4, 0x1078, - 0x18b4, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, - 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x1271, 0x70c4, 0x794c, - 0x784e, 0x0078, 0x1273, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, - 0x00c8, 0x126c, 0x1078, 0x1dc3, 0x0078, 0x1271, 0x77c4, 0x1078, - 0x18b4, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091, - 0x8001, 0x2708, 0x0078, 0x1272, 0x77c4, 0x1078, 0x18b4, 0x2091, - 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, - 0x1543, 0x1078, 0x1cf6, 0x2091, 0x8001, 0x2708, 0x0078, 0x1272, - 0x77c4, 0x1078, 0x18b4, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004, - 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1557, 0x1078, 0x1cf6, 0x2091, - 0x8001, 0x2708, 0x0078, 0x1272, 0x77c4, 0x2041, 0x0001, 0x2049, - 0x0005, 0x2051, 0x0020, 0x1078, 0x18c1, 0x2708, 0x6a08, 0x0078, - 0x1272, 0x77c4, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x1078, - 0x193c, 0x00c0, 0x1587, 0x6818, 0xa005, 0x0040, 0x1581, 0x2708, - 0x1078, 0x1dd3, 0x00c0, 0x1581, 0x7817, 0x0015, 0x2091, 0x8001, - 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x1276, 0x2091, - 0x8001, 0x0078, 0x1274, 0x77c4, 0x77c6, 0x2061, 0x3940, 0x60a3, - 0x0003, 0x67b6, 0x60c7, 0x000f, 0x2041, 0x0021, 0x2049, 0x0005, - 0x2051, 0x0020, 0x1078, 0x18c1, 0x7817, 0x0016, 0x1078, 0x1cf6, - 0x007c, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2061, 0x3940, 0x60a3, - 0x0002, 0x67b6, 0x60c7, 0x000f, 0x7817, 0x0017, 0x1078, 0x1cf6, - 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078, 0x18c1, - 0x8738, 0xa784, 0x0007, 0x00c0, 0x15b6, 0x007c, 0x78c0, 0xa084, - 0x0003, 0x00c0, 0x15e2, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, - 0x0004, 0x2051, 0x0008, 0x1078, 0x18b4, 0x2091, 0x8000, 0x6808, - 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x0007, 0x00c0, - 0x15cb, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, - 0x00c0, 0x15cb, 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, - 0x0040, 0x0040, 0x160b, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, - 0xa084, 0x0004, 0x0040, 0x15f8, 0x0070, 0x15f8, 0x0078, 0x15ef, - 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, - 0x1605, 0x0070, 0x1605, 0x0078, 0x15fc, 0x20a9, 0x00fa, 0x0070, - 0x160b, 0x0078, 0x1607, 0x2079, 0x3900, 0x7817, 0x0018, 0x2061, - 0x3940, 0x60a3, 0x0001, 0x60c7, 0x000f, 0x78c0, 0xa085, 0x0002, - 0x78c2, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0047, 0x2091, - 0x8001, 0x007c, 0x78c0, 0xa084, 0xfffd, 0x78c2, 0xa084, 0x0001, - 0x00c0, 0x162c, 0x1078, 0x197e, 0x71c4, 0x71c6, 0x794a, 0x007c, - 0x1078, 0x1a04, 0x00c0, 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de, - 0x0078, 0x163d, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc, - 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x3900, 0x1078, 0x188d, 0x0040, - 0x16e5, 0x20a9, 0x0005, 0x20a1, 0x3916, 0x41a1, 0x2009, 0x0040, - 0x1078, 0x1857, 0x0040, 0x1658, 0x1078, 0x1896, 0x0078, 0x16e5, - 0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16b9, 0x0c7e, - 0x2c68, 0x1078, 0x188d, 0x0040, 0x1688, 0x2c00, 0x689e, 0x8109, - 0x00c0, 0x1660, 0x609f, 0x0000, 0x0c7f, 0x0c7e, 0x7218, 0x731c, - 0x7420, 0x7524, 0x2c68, 0x689c, 0xa065, 0x0040, 0x16b8, 0x2009, - 0x0040, 0x1078, 0x1857, 0x00c0, 0x16a1, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0002, 0x00c0, 0x1688, 0x2d00, 0x6002, 0x0078, 0x166e, - 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6, 0x0c7f, 0x609f, - 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6008, 0xa085, 0x0200, - 0x600a, 0x6004, 0x6086, 0x1078, 0x181d, 0x1078, 0x1896, 0x0078, - 0x16e5, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6, 0x0c7f, - 0x609f, 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6087, 0x0103, - 0x601b, 0x0003, 0x1078, 0x181d, 0x1078, 0x1896, 0x0078, 0x16e5, - 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x7817, 0x0012, 0x0e7e, - 0x2071, 0x3940, 0x70a3, 0x0005, 0x70a7, 0x0000, 0x73aa, 0x72ae, - 0x74b2, 0x70b6, 0x70bb, 0x0000, 0x2c00, 0x70be, 0x70c3, 0x0000, - 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x16d9, 0x1078, - 0x330a, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x669a, 0x60af, 0x0000, - 0x60b3, 0x0000, 0x1078, 0x1cf6, 0x007c, 0x70c3, 0x4005, 0x0078, - 0x1277, 0x20a9, 0x0005, 0x2099, 0x3916, 0x530a, 0x2100, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4, - 0x70c7, 0x0000, 0x7906, 0x0078, 0x1274, 0x71c4, 0x71c6, 0x2168, - 0x0078, 0x1704, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, - 0x8d68, 0x8109, 0x00c0, 0x1706, 0xa285, 0x0000, 0x00c0, 0x1714, - 0x70c3, 0x4000, 0x0078, 0x1716, 0x70c3, 0x4003, 0x70ca, 0x0078, - 0x1277, 0x79d8, 0x0078, 0x1273, 0x71c4, 0x71c6, 0x2198, 0x20a1, - 0x0042, 0x20a9, 0x0004, 0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9, - 0x0004, 0x53a3, 0x0078, 0x1274, 0x70c4, 0x2068, 0x2079, 0x3900, - 0x1078, 0x188d, 0x0040, 0x17a4, 0x6007, 0x0001, 0x600b, 0x0000, - 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x0007, 0xa284, - 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, 0xa284, - 0x0800, 0x0040, 0x174f, 0x601b, 0x000a, 0x0078, 0x1755, 0xa284, - 0x1000, 0x0040, 0x1755, 0x601b, 0x000c, 0xa284, 0x0300, 0x0040, - 0x175e, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, 0x0001, - 0x601e, 0x6023, 0x0000, 0x6027, 0x000a, 0xa284, 0x0400, 0x0040, - 0x176b, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, 0x20a0, - 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, 0x1780, - 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, 0x178a, - 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, 0x6552, - 0x6596, 0x669a, 0x6014, 0x7817, 0x0042, 0x2c08, 0x2061, 0x3940, - 0x60a3, 0x0005, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x60af, 0x0000, - 0x60b3, 0x0000, 0x60b6, 0x61be, 0xa284, 0x0400, 0x60c2, 0x1078, - 0x32f5, 0x1078, 0x1cf6, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1277, - 0x78f0, 0xa005, 0x0040, 0x1282, 0x2091, 0x8000, 0x70c4, 0x800a, - 0x2011, 0x0010, 0x810c, 0x0048, 0x17ba, 0x3a00, 0xa084, 0xfff7, - 0x0078, 0x17bd, 0x3a00, 0xa085, 0x0008, 0x20d0, 0x0005, 0x0005, - 0xa084, 0xfffb, 0x20d0, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, - 0x0005, 0x0005, 0x0005, 0xa085, 0x0004, 0x20d0, 0x0005, 0x0005, - 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x8211, 0x00c0, - 0x17b2, 0x3a00, 0xa085, 0x0008, 0x20d0, 0x2091, 0x8001, 0x0078, - 0x1274, 0x2011, 0x04fd, 0x2204, 0xa082, 0x0004, 0x0048, 0x17f5, - 0x78f3, 0x0001, 0x2009, 0xff01, 0x200a, 0x2001, 0x000c, 0x20d8, - 0x2001, 0x000c, 0x20d0, 0x0078, 0x1274, 0x2001, 0x4005, 0x0078, - 0x1276, 0x7978, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x126c, - 0x797a, 0x0078, 0x1274, 0x7978, 0x71c6, 0x0078, 0x1274, 0x796c, - 0x71c6, 0x71c4, 0x796e, 0x7970, 0x71ca, 0x71c8, 0x7972, 0x7974, - 0x71ce, 0x71cc, 0x7976, 0x0078, 0x1274, 0x796c, 0x71c6, 0x7970, - 0x71ca, 0x7974, 0x71ce, 0x0078, 0x1274, 0x700c, 0xa084, 0x00ff, - 0x0040, 0x1829, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, - 0x1824, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e, 0x7422, 0x7526, - 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, - 0x6084, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007, - 0x0001, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1841, - 0x7108, 0x8103, 0x00c8, 0x1841, 0x7014, 0xa005, 0x0040, 0x1841, - 0x7007, 0x0002, 0xa184, 0x0060, 0x7003, 0x0000, 0x007c, 0x700c, - 0xa084, 0x00ff, 0x0040, 0x1863, 0x7007, 0x0004, 0x7004, 0xa084, - 0x0004, 0x00c0, 0x185e, 0x7017, 0x0000, 0x7112, 0x721a, 0x7422, - 0x7526, 0x731e, 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, - 0x0001, 0x7002, 0x7007, 0x0001, 0x2009, 0x0022, 0x2104, 0xa084, - 0x4000, 0x00c0, 0x1874, 0x7008, 0x800b, 0x00c8, 0x1874, 0x7007, - 0x0002, 0xa08c, 0x0060, 0x00c0, 0x188a, 0xac80, 0x0001, 0x20a0, - 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850, 0xa065, 0x0040, - 0x1895, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, - 0x3900, 0x7850, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x18a1, 0x1078, - 0x1eac, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x4400, 0x7a52, 0x7be4, - 0x8319, 0x0040, 0x18b1, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078, - 0x18a8, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, - 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3a80, - 0x007c, 0x1078, 0x18b4, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, - 0xa084, 0xffef, 0xa80d, 0x690a, 0x2091, 0x8000, 0x2009, 0x394f, - 0x210c, 0x6804, 0xa005, 0x0040, 0x18de, 0xa116, 0x00c0, 0x18de, - 0x2060, 0x6000, 0x6806, 0x017e, 0x0078, 0x18e1, 0x2009, 0x0000, - 0x017e, 0x6804, 0xa065, 0x0040, 0x18f0, 0x6000, 0x6806, 0x1078, - 0x1903, 0x1078, 0x1a14, 0x6810, 0x8001, 0x6812, 0x00c0, 0x18e1, - 0x017f, 0x6902, 0x6906, 0x2091, 0x8001, 0x007c, 0xa065, 0x0040, - 0x1902, 0x609c, 0x609f, 0x0000, 0x2008, 0x1078, 0x1896, 0x2100, - 0x0078, 0x18f6, 0x007c, 0x6007, 0x0103, 0x20a9, 0x001c, 0xac80, - 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, - 0x6022, 0x007c, 0x0e7e, 0x2071, 0x3940, 0x7040, 0xa08c, 0x0080, - 0x00c0, 0x1920, 0xa088, 0x3980, 0x2d0a, 0x8000, 0x7042, 0xa006, - 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x3940, 0x2009, 0x3980, 0x7240, - 0x8221, 0x8211, 0x0048, 0x193a, 0x2104, 0x8108, 0xad06, 0x00c0, - 0x1929, 0x8119, 0x211e, 0x8108, 0x8318, 0x8211, 0x00c8, 0x1932, - 0x7442, 0xa006, 0x0e7f, 0x007c, 0x1078, 0x18b4, 0x2091, 0x8000, - 0x6804, 0x781e, 0xa065, 0x0040, 0x197d, 0x0078, 0x194d, 0x2c00, - 0x781e, 0x6000, 0xa065, 0x0040, 0x197d, 0x6010, 0xa306, 0x00c0, - 0x1947, 0x600c, 0xa206, 0x00c0, 0x1947, 0x2c28, 0x6804, 0xac06, - 0x00c0, 0x1964, 0x6000, 0x2060, 0x6806, 0xa005, 0x00c0, 0x1964, - 0x6803, 0x0000, 0x0078, 0x196e, 0x6400, 0x781c, 0x2060, 0x6402, - 0xa486, 0x0000, 0x00c0, 0x196e, 0x2c00, 0x6802, 0x2560, 0x1078, - 0x1903, 0x601b, 0x0005, 0x6023, 0x0020, 0x1078, 0x1a14, 0x6810, - 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, 0x007c, 0x2039, 0x0000, - 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, 0x18c1, - 0x8738, 0xa784, 0x0007, 0x00c0, 0x1986, 0xa7bc, 0xff00, 0x873f, - 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1986, 0x007c, 0x2061, - 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x19a8, 0x2091, 0x8000, - 0x78d4, 0x78d7, 0x0000, 0x2091, 0x8001, 0xa005, 0x00c0, 0x19a9, - 0x007c, 0xa08c, 0xfff0, 0x0040, 0x19af, 0x1078, 0x1eac, 0x0079, - 0x19b1, 0x19c1, 0x19c3, 0x19c9, 0x19cd, 0x19c1, 0x19d1, 0x19c1, - 0x19d8, 0x19dc, 0x19e0, 0x1a0a, 0x1a0e, 0x19c1, 0x19c1, 0x19c1, - 0x19c1, 0x1078, 0x1eac, 0x1078, 0x197e, 0x2001, 0x8001, 0x0078, - 0x1276, 0x2001, 0x8003, 0x0078, 0x1276, 0x2001, 0x8004, 0x0078, - 0x1276, 0x1078, 0x197e, 0x2001, 0x8006, 0x007c, 0x0078, 0x1276, - 0x2001, 0x8008, 0x0078, 0x1276, 0x2001, 0x8009, 0x0078, 0x1276, - 0x2091, 0x8000, 0x2069, 0x3940, 0x6800, 0xa086, 0x0000, 0x0040, - 0x19ee, 0x2091, 0x8001, 0x78d7, 0x0009, 0x007c, 0x68b4, 0xa0bc, - 0xff00, 0x2091, 0x8000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, - 0x0010, 0x1078, 0x18c1, 0x8738, 0xa784, 0x0007, 0x00c0, 0x19f9, - 0x2001, 0x800a, 0x0078, 0x1276, 0x2001, 0x04fd, 0x2004, 0xa086, - 0x0004, 0x007c, 0x2001, 0x800c, 0x0078, 0x1276, 0x1078, 0x197e, - 0x2001, 0x800d, 0x0078, 0x1276, 0x6004, 0x6086, 0x2c08, 0x2063, - 0x0000, 0x787c, 0x8000, 0x787e, 0x7880, 0xa005, 0x7982, 0x0040, - 0x1a24, 0x2c02, 0x0078, 0x1a25, 0x7986, 0x007c, 0x0c7e, 0x2061, - 0x3900, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x607c, 0x8000, - 0x607e, 0x6080, 0xa005, 0x6182, 0x0040, 0x1a39, 0x2d02, 0x0078, - 0x1a3a, 0x6186, 0x0c7f, 0x007c, 0x1078, 0x1a4d, 0x0040, 0x1a4c, - 0x0c7e, 0x609c, 0xa065, 0x0040, 0x1a47, 0x1078, 0x18f6, 0x0c7f, - 0x609f, 0x0000, 0x1078, 0x1896, 0x007c, 0x7884, 0xa065, 0x0040, - 0x1a5f, 0x2091, 0x8000, 0x787c, 0x8001, 0x787e, 0x2c04, 0x7886, - 0xa005, 0x00c0, 0x1a5d, 0x7882, 0x8000, 0x2091, 0x8001, 0x007c, - 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x1a69, - 0xa200, 0x0070, 0x1a6d, 0x0078, 0x1a64, 0x8086, 0x818e, 0x007c, - 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x1a93, 0xa11a, 0x00c8, - 0x1a93, 0x8213, 0x818d, 0x0048, 0x1a84, 0xa11a, 0x00c8, 0x1a85, - 0x0070, 0x1a8b, 0x0078, 0x1a79, 0xa11a, 0x2308, 0x8210, 0x0070, - 0x1a8b, 0x0078, 0x1a79, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, - 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, - 0x1a8f, 0x798c, 0x70d0, 0x007e, 0x007f, 0xa106, 0x0040, 0x1ae9, - 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x1ae9, - 0x7008, 0x7208, 0xa206, 0x00c0, 0x1ae9, 0xa286, 0x0008, 0x00c0, - 0x1ae9, 0x2071, 0x0010, 0x1078, 0x188d, 0x0040, 0x1ae9, 0x7a94, - 0x7b90, 0x7c9c, 0x7d98, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, - 0x0000, 0x2009, 0x0040, 0x1078, 0x1857, 0x2091, 0x8001, 0x0040, - 0x1ae0, 0x1078, 0x1896, 0x78a0, 0x8000, 0x78a2, 0xa086, 0x0002, - 0x00c0, 0x1ae9, 0x2091, 0x8000, 0x78d7, 0x0002, 0x78a3, 0x0000, - 0x78c0, 0xa085, 0x0003, 0x78c2, 0x2091, 0x8001, 0x0078, 0x1ae9, - 0x78a3, 0x0000, 0x1078, 0x1c38, 0x6004, 0xa084, 0x000f, 0x0079, - 0x1aee, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x1afe, 0x1b20, - 0x1b46, 0x1afe, 0x1b58, 0x1b0d, 0x1afe, 0x1afe, 0x1afe, 0x1b1a, - 0x1b40, 0x1afe, 0x1afe, 0x1afe, 0x1afe, 0x1afe, 0x2039, 0x0400, - 0x78d0, 0xa705, 0x78d2, 0x6008, 0xa705, 0x600a, 0x1078, 0x1b96, - 0x609c, 0x78ce, 0x1078, 0x1c20, 0x007c, 0x78d0, 0xa084, 0x0100, - 0x0040, 0x1b14, 0x0078, 0x1afe, 0x601c, 0xa085, 0x0080, 0x601e, - 0x0078, 0x1b27, 0x1078, 0x1a04, 0x00c0, 0x1afe, 0x1078, 0x1c52, - 0x78d0, 0xa084, 0x0100, 0x0040, 0x1b27, 0x0078, 0x1afe, 0x78d3, - 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78c6, 0x8001, 0x609f, - 0x0000, 0x0040, 0x1b3d, 0x1078, 0x1b96, 0x0040, 0x1b3d, 0x78d0, - 0xa085, 0x0100, 0x78d2, 0x0078, 0x1b3f, 0x1078, 0x1bba, 0x007c, - 0x1078, 0x1a04, 0x00c0, 0x1afe, 0x1078, 0x1c4e, 0x78d0, 0xa08c, - 0x0e00, 0x00c0, 0x1b4f, 0xa084, 0x0100, 0x00c0, 0x1b51, 0x0078, - 0x1afe, 0x1078, 0x1b96, 0x00c0, 0x1b57, 0x1078, 0x1bba, 0x007c, - 0x78d0, 0xa084, 0x0100, 0x0040, 0x1b5f, 0x0078, 0x1afe, 0x78d3, - 0x0000, 0x6714, 0x20a9, 0x0001, 0x6018, 0xa005, 0x0040, 0x1b7a, - 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, 0x0040, 0x1b7a, - 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, 0x0040, 0x1b7a, - 0x0078, 0x1b93, 0x1078, 0x18b4, 0x2d00, 0xa088, 0x0002, 0x2091, - 0x8000, 0x2168, 0x682b, 0x0000, 0x682f, 0x0000, 0x2104, 0xa084, - 0xffde, 0x200a, 0x2100, 0xa088, 0x0010, 0x2091, 0x8001, 0x0070, - 0x1b93, 0x0078, 0x1b7f, 0x1078, 0x1896, 0x007c, 0x78c8, 0xa06d, - 0x00c0, 0x1ba1, 0x2c00, 0x78ca, 0x78ce, 0x609f, 0x0000, 0x0078, - 0x1bad, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78ca, 0x2d00, 0x6002, - 0x78cc, 0xad06, 0x00c0, 0x1bad, 0x6002, 0x78c4, 0x8001, 0x78c6, - 0x00c0, 0x1bb9, 0x78d0, 0xa084, 0x0000, 0x78d2, 0x78cc, 0x2060, - 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xc1ff, - 0x601e, 0xa184, 0x0060, 0x0040, 0x1bc9, 0x0e7e, 0x1078, 0x330a, - 0x0e7f, 0x6596, 0x669a, 0x6714, 0x1078, 0x18b4, 0x2091, 0x8000, - 0x6808, 0xa084, 0x0001, 0x0040, 0x1be5, 0x2091, 0x8001, 0x1078, - 0x1903, 0x2091, 0x8000, 0x1078, 0x1a14, 0x2091, 0x8001, 0x78cb, - 0x0000, 0x78cf, 0x0000, 0x0078, 0x1c1f, 0x6024, 0xa096, 0x0001, - 0x00c0, 0x1bec, 0x8000, 0x6026, 0x6a10, 0x6814, 0x2091, 0x8001, - 0xa202, 0x0048, 0x1bfb, 0x0040, 0x1bfb, 0x2039, 0x0200, 0x1078, - 0x1c20, 0x0078, 0x1c1f, 0x2c08, 0x2091, 0x8000, 0x6800, 0xa065, - 0x0040, 0x1c03, 0x6102, 0x6902, 0x00c0, 0x1c07, 0x6906, 0x2160, - 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808, - 0xa08c, 0x0040, 0x0040, 0x1c19, 0xa086, 0x0040, 0x680a, 0x1078, - 0x1912, 0x1078, 0x1cf6, 0x78cf, 0x0000, 0x78cb, 0x0000, 0x007c, - 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x1a14, 0x2091, - 0x8001, 0x78cc, 0xa065, 0x0040, 0x1c33, 0x609c, 0x78ce, 0x609f, - 0x0000, 0x0078, 0x1c23, 0x78cb, 0x0000, 0x78cf, 0x0000, 0x007c, - 0x7988, 0x788c, 0x8000, 0xa10a, 0x00c8, 0x1c3f, 0xa006, 0x788e, - 0x70d2, 0x7804, 0xa005, 0x0040, 0x1c4d, 0x8001, 0x7806, 0x00c0, - 0x1c4d, 0x0068, 0x1c4d, 0x2091, 0x4080, 0x007c, 0x2039, 0x1c66, - 0x0078, 0x1c54, 0x2039, 0x1c6c, 0x2704, 0xa005, 0x0040, 0x1c65, - 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, 0x6a14, 0x690a, 0x6a0e, - 0x6b12, 0x6c16, 0x8738, 0x0078, 0x1c54, 0x007c, 0x0003, 0x0009, - 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x0068, - 0x1c87, 0x2029, 0x0000, 0x7884, 0xa065, 0x0040, 0x1c82, 0x1078, - 0x1c88, 0x0040, 0x1c82, 0x1078, 0x1c99, 0x00c0, 0x1c82, 0x8528, - 0x0078, 0x1c73, 0x85ff, 0x0040, 0x1c87, 0x2091, 0x4080, 0x007c, - 0x7ba4, 0x79a8, 0x70d4, 0x007e, 0x007f, 0xa102, 0x00c0, 0x1c93, - 0x2300, 0xa005, 0x007c, 0x0048, 0x1c97, 0xa302, 0x007c, 0x8002, - 0x007c, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, - 0x1cdd, 0x7008, 0x7208, 0xa206, 0x00c0, 0x1cdd, 0xa286, 0x0008, - 0x00c0, 0x1cdd, 0x2071, 0x0010, 0x1078, 0x1ce2, 0x2009, 0x001c, - 0x6028, 0xa005, 0x0040, 0x1cb6, 0x2009, 0x0040, 0x1078, 0x181d, - 0x0040, 0x1ccf, 0x78bc, 0x8000, 0x78be, 0xa086, 0x0002, 0x00c0, - 0x1cdd, 0x2091, 0x8000, 0x78d7, 0x0003, 0x78bf, 0x0000, 0x78c0, - 0xa085, 0x0300, 0x78c2, 0x2091, 0x8001, 0x0078, 0x1cdd, 0x78bf, - 0x0000, 0x1078, 0x1a3c, 0x79a4, 0x78a8, 0x8000, 0xa10a, 0x00c8, - 0x1cda, 0xa006, 0x78aa, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, - 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, 0x7ab0, 0x7bac, 0x7cb8, - 0x7db4, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, - 0x007c, 0x2009, 0x3968, 0x2091, 0x8000, 0x200a, 0x0f7e, 0x2079, - 0x0100, 0x2009, 0x3940, 0x2091, 0x8000, 0x2104, 0xa086, 0x0000, - 0x00c0, 0x1d11, 0x2009, 0x3912, 0x2104, 0xa005, 0x00c0, 0x1d11, - 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1d11, 0x0018, 0x1d11, 0x781b, - 0x0045, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, - 0x2071, 0x3940, 0x2079, 0x0100, 0x784b, 0x000f, 0x2019, 0x3205, - 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1d2f, 0x789a, 0x8318, - 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1d22, 0x789b, - 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0020, 0x0070, - 0x1d3b, 0x0078, 0x1d33, 0x7003, 0x0000, 0x1078, 0x1e40, 0x7004, - 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200, 0x7843, - 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x397f, 0x7043, - 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, - 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1e40, 0x007c, - 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1d69, 0x0078, - 0x1d64, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, - 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x1d7a, - 0x0078, 0x1d75, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, - 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, - 0x1d8b, 0x0078, 0x1d86, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, - 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, - 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, - 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, - 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, - 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, - 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, - 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, - 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, - 0x2018, 0x0c7f, 0x007c, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, - 0x1e1c, 0x2061, 0x4380, 0x1078, 0x1e22, 0x0040, 0x1e06, 0x20a9, - 0x0000, 0x2061, 0x4280, 0x0c7e, 0x1078, 0x1e22, 0x0040, 0x1df0, - 0x0c7f, 0x8c60, 0x0070, 0x1dee, 0x0078, 0x1de3, 0x0078, 0x1e1c, - 0x007f, 0xa082, 0x4280, 0x2071, 0x3940, 0x70ba, 0x6020, 0xa085, - 0x0800, 0x6022, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0004, 0x70a2, - 0x70c7, 0x000f, 0x1078, 0x1cf1, 0x0078, 0x1e18, 0x2071, 0x3940, - 0x6020, 0xa085, 0x0800, 0x6022, 0x2091, 0x8001, 0x71b6, 0x2c00, - 0x70be, 0x2001, 0x0006, 0x70a2, 0x70c7, 0x000f, 0x1078, 0x1cf1, - 0x2001, 0x0000, 0x0078, 0x1e1e, 0x2001, 0x0001, 0xa005, 0x0e7f, - 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04, 0xa005, 0x0040, 0x1e3b, - 0x2060, 0x6010, 0xa306, 0x00c0, 0x1e38, 0x600c, 0xa206, 0x00c0, - 0x1e38, 0x6014, 0xa106, 0x00c0, 0x1e38, 0xa006, 0x0078, 0x1e3f, - 0x6000, 0x0078, 0x1e25, 0xa085, 0x0001, 0x2091, 0x8001, 0x007c, - 0x2011, 0x3941, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, - 0xa084, 0x0100, 0x0040, 0x1e56, 0x2021, 0xff04, 0x2122, 0x810b, - 0x810b, 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e, - 0x68e4, 0xa08c, 0x0020, 0x0040, 0x1eaa, 0xa084, 0x0006, 0x00c0, - 0x1eaa, 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xa0f0, 0x3a00, 0x7004, 0xa084, 0x000a, 0x00c0, 0x1eaa, 0x7108, - 0xa194, 0xff00, 0x0040, 0x1eaa, 0xa18c, 0x00ff, 0x2001, 0x000c, - 0xa106, 0x0040, 0x1e91, 0x2001, 0x0012, 0xa106, 0x0040, 0x1e95, - 0x2001, 0x0014, 0xa106, 0x0040, 0x1e99, 0x2001, 0x0019, 0xa106, - 0x0040, 0x1e9d, 0x2001, 0x0032, 0xa106, 0x0040, 0x1ea1, 0x0078, - 0x1ea5, 0x2009, 0x0012, 0x0078, 0x1ea7, 0x2009, 0x0014, 0x0078, - 0x1ea7, 0x2009, 0x0019, 0x0078, 0x1ea7, 0x2009, 0x0020, 0x0078, - 0x1ea7, 0x2009, 0x003f, 0x0078, 0x1ea7, 0x2011, 0x0000, 0x2100, - 0xa205, 0x700a, 0x0e7f, 0x007c, 0x2071, 0x0010, 0x70ca, 0x007f, - 0x70c6, 0x70c3, 0x8002, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, - 0x4080, 0x0078, 0x1eb9, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300, - 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x2009, 0x3974, 0x78a0, 0x200a, - 0x8108, 0x250a, 0x8108, 0x240a, 0x8108, 0x260a, 0x8108, 0x270a, - 0xa594, 0x003f, 0xa484, 0x4000, 0x0040, 0x1edc, 0xa784, 0x007c, - 0x00c0, 0x318f, 0x1078, 0x1eac, 0xa49c, 0x000f, 0xa382, 0x0004, - 0x0050, 0x1ee4, 0x1078, 0x1eac, 0x8507, 0xa084, 0x000f, 0x0079, - 0x1ee9, 0x236e, 0x240d, 0x242e, 0x2699, 0x28dd, 0x293b, 0x2984, - 0x29f0, 0x2a8d, 0x2b1a, 0x1f11, 0x1ef9, 0x21c3, 0x2288, 0x28bc, - 0x1ef9, 0x1078, 0x1eac, 0x0018, 0x1ec0, 0x127f, 0x2091, 0x8001, - 0x007f, 0x107f, 0x007c, 0x7003, 0x0000, 0x703f, 0x0000, 0x7030, - 0xa005, 0x0040, 0x1f0d, 0x7033, 0x0000, 0x1078, 0x316a, 0x0018, - 0x1ec0, 0x2009, 0x390f, 0x200b, 0x0000, 0x705c, 0xa005, 0x00c0, - 0x1fe2, 0x70a0, 0xa084, 0x0007, 0x0079, 0x1f1e, 0x2005, 0x1f26, - 0x1f34, 0x1f51, 0x1f73, 0x1fc0, 0x1f99, 0x1f26, 0x7808, 0xa084, - 0xfffd, 0x780a, 0x2009, 0x0047, 0x1078, 0x27c1, 0x00c0, 0x1f32, - 0x7003, 0x0004, 0x0078, 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f4f, - 0x70b4, 0x8007, 0x7882, 0x789b, 0x0010, 0x78ab, 0x000c, 0x789b, - 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00fb, 0x1078, - 0x27bf, 0x00c0, 0x1f4f, 0x7003, 0x0004, 0x70c7, 0x000f, 0x0078, - 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f71, 0x71b4, 0x8107, 0x7882, - 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, - 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009, - 0x00fb, 0x1078, 0x27bf, 0x00c0, 0x1f71, 0x7003, 0x0004, 0x70c7, - 0x000f, 0x0078, 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f97, 0x71b4, - 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, - 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, 0x789b, - 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00fb, 0x1078, - 0x27bf, 0x00c0, 0x1f97, 0x7003, 0x0004, 0x70c7, 0x000f, 0x0078, - 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1fbe, 0x71b4, 0x8107, 0x7882, - 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, - 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009, - 0x00fb, 0x1078, 0x27bf, 0x00c0, 0x1fbe, 0x70bc, 0x70bf, 0x0000, - 0x2068, 0x703e, 0x7003, 0x0002, 0x70c7, 0x000f, 0x0078, 0x1efb, - 0x1078, 0x3151, 0x00c0, 0x1efb, 0x70bc, 0x2068, 0x1078, 0x31f3, - 0x789b, 0x0010, 0x6814, 0xa084, 0x0007, 0xa085, 0x0080, 0x007e, - 0x007f, 0x78aa, 0x6e1c, 0x067e, 0x067f, 0x2041, 0x0001, 0x70c0, - 0xa084, 0x0400, 0x2001, 0x0004, 0x0040, 0x1fe0, 0x2001, 0x0006, - 0x0078, 0x20e1, 0x1078, 0x3151, 0x00c0, 0x1efb, 0x789b, 0x0010, - 0x705c, 0x2068, 0x1078, 0x31f3, 0x6f14, 0x1078, 0x3099, 0x6008, - 0xa085, 0x0010, 0x600a, 0xad80, 0x0009, 0x2003, 0x0005, 0x6814, - 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, 0x0020, 0x2041, - 0x0001, 0x2001, 0x0003, 0x0078, 0x20e1, 0x0018, 0x1ec0, 0x7440, - 0xa485, 0x0000, 0x0040, 0x201f, 0xa080, 0x3980, 0x2030, 0x7144, - 0x8108, 0xa12a, 0x0048, 0x2016, 0x2009, 0x3980, 0x2164, 0x6504, - 0x85ff, 0x00c0, 0x202c, 0x8421, 0x00c0, 0x2010, 0x7146, 0x7003, - 0x0000, 0x703f, 0x0000, 0x0078, 0x1efb, 0x7640, 0xa6b0, 0x3980, - 0x7144, 0x2600, 0x0078, 0x201b, 0x7146, 0x2568, 0x2558, 0x753e, - 0x2c50, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, 0x2059, 0xa784, - 0x0021, 0x00c0, 0x2029, 0xa784, 0x0002, 0x0040, 0x2046, 0xa784, - 0x0004, 0x0040, 0x2029, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, - 0x00c0, 0x2029, 0xa784, 0x0010, 0x00c0, 0x2029, 0xa784, 0x0100, - 0x0040, 0x2059, 0x6018, 0xa005, 0x00c0, 0x2029, 0xa7bc, 0xfeff, - 0x670a, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6118, 0x0040, - 0x2069, 0x601c, 0xa102, 0x0048, 0x206c, 0x0040, 0x206c, 0x0078, - 0x2025, 0x81ff, 0x00c0, 0x2025, 0xa784, 0x0080, 0x00c0, 0x2072, - 0x700c, 0x6022, 0x1078, 0x31f3, 0x0018, 0x1ec0, 0x789b, 0x0010, - 0xa046, 0x1078, 0x3151, 0x00c0, 0x1efb, 0x6b14, 0xa39c, 0x0007, - 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, 0x0040, 0x208b, 0xa684, - 0x0001, 0x0040, 0x208d, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040, - 0x2093, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0, - 0x209e, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x20df, 0x714c, 0xa18c, - 0x0800, 0x0040, 0x2cfc, 0x2011, 0x0021, 0x8004, 0x8004, 0x0048, - 0x20b5, 0x2011, 0x0022, 0x8004, 0x0048, 0x20b5, 0x2011, 0x0020, - 0x8004, 0x0048, 0x20b5, 0x0040, 0x20df, 0x7aaa, 0x8840, 0x1078, - 0x316a, 0x6a14, 0x610c, 0x8108, 0xa18c, 0x00ff, 0xa1e0, 0x4280, - 0x2c64, 0x8cff, 0x0040, 0x20d6, 0x6014, 0xa206, 0x00c0, 0x20c0, - 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x20bb, 0x0c7e, 0x2a60, 0x6008, - 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x2005, 0x1078, 0x3151, - 0x00c0, 0x1efb, 0x2a60, 0x610e, 0x79aa, 0x8840, 0x712e, 0x2001, - 0x0001, 0x007e, 0x7150, 0xa184, 0x0018, 0x0040, 0x20fc, 0xa184, - 0x0010, 0x0040, 0x20ef, 0x1078, 0x2ee3, 0x00c0, 0x211f, 0xa184, - 0x0008, 0x0040, 0x20fc, 0x69a0, 0xa184, 0x0600, 0x00c0, 0x20fc, - 0x1078, 0x2ddf, 0x0078, 0x211f, 0x69a0, 0xa184, 0x0800, 0x0040, - 0x2113, 0x0c7e, 0x027e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, - 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f, 0x0c7f, 0x1078, 0x2ee3, - 0x00c0, 0x211f, 0x69a0, 0xa184, 0x0200, 0x0040, 0x211b, 0x1078, - 0x2e2e, 0x0078, 0x211f, 0xa184, 0x0400, 0x00c0, 0x20f8, 0x69a0, - 0xa184, 0x1000, 0x0040, 0x212a, 0x6914, 0xa18c, 0xff00, 0x810f, - 0x1078, 0x1da7, 0x007f, 0x7002, 0xa68c, 0x00e0, 0xa684, 0x0060, - 0x0040, 0x2138, 0xa086, 0x0060, 0x00c0, 0x2138, 0xa18d, 0x4000, - 0x88ff, 0x0040, 0x213d, 0xa18d, 0x0004, 0x795a, 0x69b6, 0x789b, - 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6818, 0xa08d, 0x8000, - 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080, 0x0040, 0x215c, 0x70cb, - 0x0000, 0xa08a, 0x000d, 0x0050, 0x215a, 0xa08a, 0x000c, 0x71ca, - 0x2001, 0x000c, 0x800c, 0x71ce, 0x78aa, 0x8008, 0x810c, 0x0040, - 0x2d07, 0xa18c, 0x00f8, 0x00c0, 0x2d07, 0x157e, 0x137e, 0x147e, - 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, - 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882, - 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2, 0x7eda, 0x7830, 0xa084, - 0x00c0, 0x00c0, 0x2185, 0x0098, 0x218d, 0x6008, 0xa084, 0xffef, - 0x600a, 0x1078, 0x316a, 0x0078, 0x1f03, 0x7200, 0xa284, 0x0007, - 0xa086, 0x0001, 0x00c0, 0x219a, 0x781b, 0x004a, 0x1078, 0x316a, - 0x0078, 0x21ab, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x004a, - 0x1078, 0x316a, 0x7200, 0x2500, 0xa605, 0x0040, 0x21ab, 0xa284, - 0x0007, 0x1079, 0x21b9, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, - 0x1efb, 0x6018, 0x8000, 0x601a, 0xad80, 0x0009, 0x7032, 0x0078, - 0x1efb, 0x21c1, 0x3571, 0x3571, 0x3560, 0x3571, 0x21c1, 0x3560, - 0x21c1, 0x1078, 0x1eac, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, - 0x2079, 0x3900, 0x78c0, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x21e9, - 0x70a0, 0xa086, 0x0001, 0x00c0, 0x21d8, 0x70a2, 0x0078, 0x226c, - 0x70a0, 0xa086, 0x0005, 0x00c0, 0x21e7, 0x70bc, 0x2068, 0x681b, - 0x0004, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x70a3, - 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, 0xa186, 0x0001, 0x0040, - 0x2207, 0xa186, 0x0007, 0x00c0, 0x21fb, 0x2009, 0x3935, 0x200b, - 0x0005, 0x0078, 0x2207, 0x2009, 0x3913, 0x2104, 0x2009, 0x3912, - 0x200a, 0x2009, 0x3935, 0x200b, 0x0001, 0x0078, 0x2209, 0x70a3, - 0x0000, 0x1078, 0x32f5, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, - 0x2f9a, 0xa7b8, 0x0100, 0x0070, 0x2217, 0x0078, 0x220f, 0x7000, - 0x0079, 0x221a, 0x2248, 0x2231, 0x2231, 0x2224, 0x2248, 0x2248, - 0x2248, 0x2222, 0x1078, 0x1eac, 0x2021, 0x3957, 0x2404, 0xa005, - 0x0040, 0x2248, 0xad06, 0x00c0, 0x2231, 0x6800, 0x2022, 0x0078, - 0x2241, 0x6820, 0xa084, 0x0001, 0x00c0, 0x223d, 0x6f14, 0x1078, - 0x3099, 0x1078, 0x2cc9, 0x0078, 0x2241, 0x7054, 0x2060, 0x6800, - 0x6002, 0x6a1a, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078, 0x1a26, - 0x2021, 0x4380, 0x1078, 0x2272, 0x2021, 0x3957, 0x1078, 0x2272, - 0x20a9, 0x0000, 0x2021, 0x4280, 0x1078, 0x2272, 0x8420, 0x0070, - 0x225b, 0x0078, 0x2254, 0x20a9, 0x0080, 0x2061, 0x3a80, 0x6018, - 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, - 0x226b, 0x0078, 0x225f, 0x157f, 0x7003, 0x0000, 0x703f, 0x0000, - 0x0078, 0x1efb, 0x047e, 0x2404, 0xa005, 0x0040, 0x2284, 0x2068, - 0x6800, 0x007e, 0x6a1a, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078, - 0x1a26, 0x007f, 0x0078, 0x2274, 0x047f, 0x2023, 0x0000, 0x007c, - 0xa282, 0x0003, 0x0050, 0x228e, 0x1078, 0x1eac, 0x2300, 0x0079, - 0x2291, 0x2294, 0x2311, 0x232e, 0xa282, 0x0002, 0x0040, 0x229a, - 0x1078, 0x1eac, 0x70a0, 0x70a3, 0x0000, 0x70c7, 0x0000, 0x0079, - 0x22a1, 0x22a9, 0x22a9, 0x22ab, 0x22e9, 0x2d0d, 0x22a9, 0x22e9, - 0x22a9, 0x1078, 0x1eac, 0x77b4, 0x1078, 0x2f9a, 0x77b4, 0xa7bc, - 0x0f00, 0x1078, 0x3099, 0x6018, 0xa005, 0x0040, 0x22e0, 0x2021, - 0x4380, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x0040, - 0x22e0, 0x157e, 0x20a9, 0x0000, 0x2021, 0x4280, 0x047e, 0x2009, - 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x047f, 0x0040, 0x22d5, - 0x8420, 0x0070, 0x22d5, 0x0078, 0x22c6, 0x157f, 0x2021, 0x3957, - 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x0040, 0x22e0, - 0x8738, 0xa784, 0x0007, 0x00c0, 0x22b1, 0x0078, 0x1f03, 0x0078, - 0x1f03, 0x77b4, 0x1078, 0x3099, 0x6018, 0xa005, 0x0040, 0x230f, - 0x2021, 0x4380, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x2349, - 0x0040, 0x230f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x4280, 0x047e, - 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x2349, 0x047f, 0x0040, - 0x230e, 0x8420, 0x0070, 0x230e, 0x0078, 0x22ff, 0x157f, 0x0078, - 0x1f03, 0x2200, 0x0079, 0x2314, 0x2317, 0x2319, 0x2319, 0x1078, - 0x1eac, 0x2009, 0x0012, 0x70a0, 0xa086, 0x0002, 0x0040, 0x2322, - 0x2009, 0x000e, 0x6818, 0xa084, 0x8000, 0x0040, 0x2328, 0x691a, - 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x311c, 0x2200, 0x0079, - 0x2331, 0x2336, 0x2319, 0x2334, 0x1078, 0x1eac, 0x1078, 0x27ce, - 0x7000, 0xa086, 0x0001, 0x00c0, 0x2c9f, 0x1078, 0x2cdf, 0x6008, - 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x2c9f, 0x0078, - 0x2005, 0x2404, 0xa005, 0x0040, 0x236a, 0x2068, 0x2d04, 0x007e, - 0x6814, 0xa706, 0x0040, 0x2358, 0x2d20, 0x007f, 0x0078, 0x234a, - 0x007f, 0x2022, 0x691a, 0x6820, 0xa205, 0x6822, 0x1078, 0x1a26, - 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, - 0x2cdf, 0x007c, 0xa085, 0x0001, 0x0078, 0x2369, 0x2300, 0x0079, - 0x2371, 0x2376, 0x2374, 0x23c2, 0x1078, 0x1eac, 0x78e4, 0xa005, - 0x00d0, 0x238a, 0x0018, 0x238a, 0xa084, 0x0007, 0x0079, 0x2380, - 0x239b, 0x23a8, 0x238e, 0x2388, 0x3144, 0x3144, 0x2388, 0x23b5, - 0x1078, 0x1eac, 0x2001, 0x0003, 0x0078, 0x26ad, 0x6818, 0xa084, - 0x8000, 0x0040, 0x2395, 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b, - 0x0053, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040, 0x23a2, - 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b, 0x00de, 0x0078, 0x1efb, - 0x6818, 0xa084, 0x8000, 0x0040, 0x23af, 0x681b, 0x001d, 0x1078, - 0x2f7d, 0x781b, 0x00e5, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, - 0x0040, 0x23bc, 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b, 0x009c, - 0x0078, 0x1efb, 0xa584, 0x000f, 0x00c0, 0x23e1, 0x1078, 0x27ce, - 0x7000, 0x0079, 0x23cb, 0x23d3, 0x23d5, 0x23d3, 0x2c9f, 0x2c9f, - 0x2c9f, 0x2c9f, 0x23d3, 0x1078, 0x1eac, 0x1078, 0x2cdf, 0x6008, - 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x2c9f, 0x0078, - 0x2005, 0x79e4, 0xa005, 0x00d0, 0x238a, 0x0018, 0x238a, 0xa184, - 0x0007, 0x0079, 0x23eb, 0x23fb, 0x2401, 0x23f5, 0x23f3, 0x3144, - 0x3144, 0x23f3, 0x313c, 0x1078, 0x1eac, 0x1078, 0x2f85, 0x781b, - 0x0053, 0x0078, 0x1efb, 0x1078, 0x2f85, 0x781b, 0x00de, 0x0078, - 0x1efb, 0x1078, 0x2f85, 0x781b, 0x00e5, 0x0078, 0x1efb, 0x1078, - 0x2f85, 0x781b, 0x009c, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2410, - 0x2415, 0x2413, 0x2417, 0x1078, 0x1eac, 0x0078, 0x29f0, 0x681b, - 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x29f0, - 0xa184, 0x0007, 0x0079, 0x2424, 0x242c, 0x2401, 0x238e, 0x311c, - 0x3144, 0x3144, 0x242c, 0x313c, 0x1078, 0x1eac, 0xa282, 0x0005, - 0x0050, 0x2434, 0x1078, 0x1eac, 0x2300, 0x0079, 0x2437, 0x243a, - 0x265e, 0x266a, 0x2200, 0x0079, 0x243d, 0x2457, 0x2444, 0x2457, - 0x2442, 0x2643, 0x1078, 0x1eac, 0x789b, 0x0018, 0x78a8, 0xa084, - 0x00ff, 0xa082, 0x0020, 0x0048, 0x2f69, 0xa08a, 0x0004, 0x00c8, - 0x2f69, 0x0079, 0x2453, 0x2f69, 0x2f69, 0x2f69, 0x2f23, 0x789b, - 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x246c, 0xa184, 0x0018, - 0x0040, 0x2468, 0x0078, 0x2f69, 0x7000, 0xa005, 0x00c0, 0x2462, - 0x2011, 0x0004, 0x0078, 0x2b28, 0xa184, 0x00ff, 0xa08a, 0x0010, - 0x00c8, 0x2f69, 0x0079, 0x2474, 0x2486, 0x2484, 0x249e, 0x24a2, - 0x255a, 0x2f69, 0x2f69, 0x255c, 0x2f69, 0x2f69, 0x263f, 0x263f, - 0x2f69, 0x2f69, 0x2f69, 0x2641, 0x1078, 0x1eac, 0xa684, 0x1000, - 0x0040, 0x2493, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, - 0x0099, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040, 0x249c, - 0x681b, 0x001d, 0x0078, 0x248a, 0x0078, 0x311c, 0x681b, 0x001d, - 0x0078, 0x2f75, 0x6920, 0xa184, 0x8000, 0x00c0, 0x24ae, 0x68af, - 0x0000, 0x68b3, 0x0000, 0xa18d, 0x8000, 0x6922, 0xa684, 0x1800, - 0x00c0, 0x24ed, 0x6820, 0xa084, 0x0001, 0x00c0, 0x24f3, 0x6818, - 0xa086, 0x0008, 0x00c0, 0x24be, 0x681b, 0x0000, 0xa684, 0x0400, - 0x0040, 0x2556, 0xa684, 0x0080, 0x0040, 0x24e9, 0x70cb, 0x0000, - 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x24e9, 0xa08a, - 0x000c, 0x71ca, 0x2001, 0x000c, 0x800c, 0x71ce, 0x789b, 0x0061, - 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, - 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, - 0x157f, 0x781b, 0x0056, 0x0078, 0x1efb, 0xa684, 0x1000, 0x0040, - 0x24f3, 0x0078, 0x1efb, 0xa684, 0x0060, 0x0040, 0x2552, 0xa684, - 0x0800, 0x0040, 0x2552, 0xa684, 0x8000, 0x00c0, 0x2503, 0x69b0, - 0x6aac, 0x0078, 0x251d, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x789b, - 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2510, 0x8000, - 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, - 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, - 0x2525, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb6, 0xa006, 0x1078, 0x362f, - 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x2534, - 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x6ba6, 0x7bd6, - 0x2300, 0xa405, 0x00c0, 0x2544, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, - 0x781b, 0x0065, 0x0078, 0x1efb, 0x781b, 0x0065, 0x2200, 0xa115, - 0x00c0, 0x254e, 0x1078, 0x3571, 0x0078, 0x1efb, 0x1078, 0x35a6, - 0x0078, 0x1efb, 0x781b, 0x0068, 0x0078, 0x1efb, 0x781b, 0x0056, - 0x0078, 0x1efb, 0x1078, 0x1eac, 0x0078, 0x25b1, 0x6920, 0xa184, - 0x0100, 0x0040, 0x2570, 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7048, - 0x2060, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x25a0, - 0xa184, 0x0200, 0x0040, 0x25a0, 0xa18c, 0xfdff, 0x6922, 0x0c7e, - 0x7048, 0x2060, 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, - 0x0c7f, 0xa184, 0x0008, 0x0040, 0x25a0, 0x1078, 0x3095, 0x1078, - 0x2ddf, 0x88ff, 0x0040, 0x25a0, 0x789b, 0x0060, 0x2800, 0x78aa, - 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x259c, - 0x781b, 0x0053, 0x0078, 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb, - 0x7e58, 0xa684, 0x0400, 0x00c0, 0x25a9, 0x781b, 0x0056, 0x0078, - 0x1efb, 0x781b, 0x0068, 0x0078, 0x1efb, 0x0078, 0x2f6f, 0x0078, - 0x2f6f, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x25af, - 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0, - 0x25d4, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x25cc, - 0x0048, 0x25cc, 0x0078, 0x25ce, 0x0078, 0x255e, 0x24a8, 0x7aa8, - 0x00f0, 0x25ce, 0x0078, 0x25ba, 0xa284, 0x00f0, 0xa086, 0x0020, - 0x00c0, 0x2630, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x25e4, - 0x0048, 0x25e4, 0x0078, 0x262d, 0xa286, 0x0023, 0x0040, 0x25af, - 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xa085, - 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, 0x600a, 0x0c7e, - 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0010, - 0x0040, 0x2608, 0x1078, 0x3095, 0x1078, 0x2ee3, 0x0078, 0x2617, - 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, - 0x0008, 0x0040, 0x25a0, 0x1078, 0x3095, 0x1078, 0x2ddf, 0x88ff, - 0x0040, 0x25a0, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004, - 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2629, 0x781b, 0x0053, 0x0078, - 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb, 0x7aa8, 0x0078, 0x25ba, - 0x8318, 0x2300, 0xa102, 0x0040, 0x2639, 0x0048, 0x2639, 0x0078, - 0x25ba, 0xa284, 0x0080, 0x00c0, 0x2f75, 0x0078, 0x2f6f, 0x0078, - 0x2f75, 0x0078, 0x2f69, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, - 0xa08e, 0x0001, 0x0040, 0x264e, 0x1078, 0x1eac, 0x7aa8, 0xa294, - 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2f69, - 0x0079, 0x265a, 0x2f69, 0x2d32, 0x2f69, 0x2e7e, 0xa282, 0x0000, - 0x00c0, 0x2664, 0x1078, 0x1eac, 0x1078, 0x2f7d, 0x781b, 0x0067, - 0x0078, 0x1efb, 0xa282, 0x0003, 0x00c0, 0x2670, 0x1078, 0x1eac, - 0xa484, 0x8000, 0x00c0, 0x2693, 0x70a0, 0xa005, 0x0040, 0x267a, - 0x1078, 0x1eac, 0x6f14, 0x77b6, 0xa7bc, 0x0f00, 0x1078, 0x3099, - 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x0007, 0x00c0, - 0x267e, 0x1078, 0x2f81, 0x70a3, 0x0002, 0x2009, 0x3935, 0x200b, - 0x0009, 0x0078, 0x2695, 0x1078, 0x2f8d, 0x781b, 0x0067, 0x0078, - 0x1efb, 0xa282, 0x0004, 0x0050, 0x269f, 0x1078, 0x1eac, 0x2300, - 0x0079, 0x26a2, 0x26a5, 0x2781, 0x27a9, 0xa286, 0x0003, 0x0040, - 0x26ab, 0x1078, 0x1eac, 0x2001, 0x0000, 0x703a, 0x7000, 0xa084, - 0x0007, 0x0079, 0x26b3, 0x26bb, 0x26bd, 0x26bd, 0x2871, 0x28a2, - 0x1f03, 0x28a2, 0x26bb, 0x1078, 0x1eac, 0xa684, 0x1000, 0x00c0, - 0x26c5, 0x1078, 0x32f5, 0x0040, 0x275b, 0x7868, 0xa08c, 0x00ff, - 0x0040, 0x270d, 0xa186, 0x0008, 0x00c0, 0x26dc, 0x1078, 0x2cdf, - 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x270d, - 0x1078, 0x32f5, 0x0078, 0x26f4, 0xa186, 0x0028, 0x00c0, 0x270d, - 0x1078, 0x32f5, 0x6008, 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, - 0x0040, 0x26f4, 0x8001, 0x601a, 0xa005, 0x0040, 0x26f4, 0x8001, - 0xa005, 0x0040, 0x26f4, 0x601e, 0x6820, 0xa084, 0x0001, 0x0040, - 0x1f03, 0x6820, 0xa084, 0xfffe, 0x6822, 0x7054, 0x0c7e, 0x2060, - 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, - 0x270a, 0x6002, 0x6006, 0x0078, 0x1f03, 0x017e, 0x1078, 0x27ce, - 0x017f, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0x81ff, - 0x0040, 0x275b, 0xa186, 0x0002, 0x00c0, 0x2753, 0xa684, 0x0800, - 0x00c0, 0x272a, 0xa684, 0x0060, 0x0040, 0x272a, 0x78d8, 0x7adc, - 0x682e, 0x6a32, 0x6820, 0xa084, 0x0800, 0x00c0, 0x275b, 0x8717, - 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3a00, 0xa290, - 0x0000, 0x221c, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, 0x8211, - 0xa384, 0x0400, 0x0040, 0x274d, 0x68a0, 0xa084, 0x0100, 0x00c0, - 0x274d, 0x1078, 0x2830, 0x0078, 0x1f03, 0x6008, 0xa085, 0x0002, - 0x600a, 0x0078, 0x275b, 0xa186, 0x0018, 0x0040, 0x275b, 0xa186, - 0x0014, 0x0040, 0x1f03, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040, - 0x2763, 0x7038, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x2cd0, - 0x1078, 0x2cdf, 0x00c0, 0x2770, 0x6008, 0xa084, 0xffef, 0x600a, - 0x6820, 0xa084, 0x0001, 0x00c0, 0x2779, 0x1078, 0x2cc9, 0x0078, - 0x277d, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x1a26, 0x0078, - 0x1f03, 0xa282, 0x0004, 0x0048, 0x2787, 0x1078, 0x1eac, 0x2200, - 0x0079, 0x278a, 0x2785, 0x278e, 0x2794, 0x278e, 0x1078, 0x2f7d, - 0x781b, 0x0067, 0x0078, 0x1efb, 0x7890, 0x8007, 0x8001, 0xa084, - 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, - 0x0003, 0x0040, 0x27a5, 0x0078, 0x2f69, 0x781b, 0x0068, 0x0078, - 0x1efb, 0x6820, 0xa085, 0x0004, 0x6822, 0x82ff, 0x00c0, 0x27b4, - 0x1078, 0x2f7d, 0x0078, 0x27bb, 0x8211, 0x0040, 0x27b9, 0x1078, - 0x1eac, 0x1078, 0x2f8d, 0x781b, 0x0067, 0x0078, 0x1efb, 0x1078, - 0x316a, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x27cb, 0x0018, 0x27cb, - 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, - 0x00c0, 0x27d8, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x282f, - 0xa684, 0x0800, 0x00c0, 0x27e8, 0x6998, 0x6a94, 0x692e, 0x6a32, - 0x7000, 0xa086, 0x0006, 0x0040, 0x27e7, 0x1078, 0x32f5, 0x007c, - 0xa684, 0x0020, 0x0040, 0x2802, 0xa684, 0x4000, 0x0040, 0x27f6, - 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x27e0, 0x7038, 0xa005, - 0x00c0, 0x27fc, 0x703b, 0x0015, 0x79d8, 0x7adc, 0x692e, 0x6a32, - 0x0078, 0x27e0, 0xa684, 0x4000, 0x0040, 0x280c, 0x682f, 0x0000, - 0x6833, 0x0000, 0x0078, 0x27e0, 0x7038, 0xa005, 0x00c0, 0x2812, - 0x703b, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8, 0x2819, + 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1387, 0x8001, 0x78ae, + 0xa084, 0xfc00, 0x0040, 0x137c, 0x78cc, 0xa085, 0x0100, 0x78ce, + 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba, 0x7dbe, 0x7ec2, + 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078, 0x138b, 0x78cc, + 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009, 0x5061, 0x210c, + 0x7aec, 0x0078, 0x1282, 0x2009, 0x5041, 0x210c, 0x0078, 0x1283, + 0x2009, 0x5042, 0x210c, 0x0078, 0x1283, 0x2061, 0x5040, 0x610c, + 0x6210, 0x0078, 0x1282, 0x2009, 0x5045, 0x210c, 0x0078, 0x1283, + 0x2009, 0x5046, 0x210c, 0x0078, 0x1283, 0x2009, 0x5048, 0x210c, + 0x0078, 0x1283, 0x2009, 0x5049, 0x210c, 0x0078, 0x1283, 0x7908, + 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa0e8, 0x5280, 0x6a00, 0x6804, 0xa084, 0x0008, + 0x0040, 0x13cd, 0x6b08, 0x0078, 0x13ce, 0x6b0c, 0x0078, 0x1281, + 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, + 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078, 0x1283, 0x77c4, + 0x1078, 0x1956, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091, + 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x127c, + 0x1078, 0x22c1, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8, + 0x127c, 0x2011, 0x5041, 0x2204, 0x007e, 0x2112, 0x1078, 0x227a, + 0x017f, 0x0078, 0x1283, 0x71c4, 0x2011, 0x1421, 0x20a9, 0x0008, + 0x2204, 0xa106, 0x0040, 0x1413, 0x8210, 0x0070, 0x1411, 0x0078, + 0x1408, 0x0078, 0x127c, 0xa292, 0x1421, 0x027e, 0x2011, 0x5042, + 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x2286, 0x017f, 0x0078, + 0x1283, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, + 0x004b, 0x2061, 0x5040, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8, + 0x6012, 0x0078, 0x1282, 0x2061, 0x5040, 0x6114, 0x70c4, 0x6016, + 0x0078, 0x1283, 0x2061, 0x5040, 0x71c4, 0x2011, 0x0004, 0x601f, + 0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x145b, 0x2011, + 0x0005, 0x601f, 0x0019, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, + 0x145b, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186, + 0x003c, 0x00c0, 0x127c, 0x6018, 0x007e, 0x611a, 0x7800, 0xa084, + 0x0001, 0x00c0, 0x1476, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, + 0x0048, 0x146e, 0x0038, 0x1472, 0x0078, 0x1476, 0x0028, 0x1472, + 0x0078, 0x1476, 0x2019, 0x2222, 0x0078, 0x1478, 0x2019, 0x1212, + 0x23b8, 0x1078, 0x2297, 0x1078, 0x4bdf, 0x017f, 0x0078, 0x1283, + 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5048, 0x2204, + 0x2112, 0x007e, 0x1078, 0x22b9, 0x017f, 0x0078, 0x1283, 0x71c4, + 0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5049, 0x2204, 0x007e, + 0x2112, 0x1078, 0x22a8, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8, + 0xa184, 0xfffd, 0x00c0, 0x127b, 0xa284, 0xfffd, 0x00c0, 0x127b, + 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x1282, + 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, + 0x5280, 0x2019, 0x0000, 0x72c8, 0xa284, 0x0080, 0x0040, 0x14c6, + 0x6c14, 0x84ff, 0x00c0, 0x14c6, 0x6817, 0x0040, 0xa284, 0x0040, + 0x0040, 0x14d0, 0x6c10, 0x84ff, 0x00c0, 0x14d0, 0x6813, 0x0001, + 0x6800, 0x007e, 0xa226, 0x0040, 0x14f3, 0x6a02, 0xa484, 0x2000, + 0x0040, 0x14dc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14e2, + 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14f3, 0x810f, 0xa284, + 0x4000, 0x0040, 0x14ef, 0x1078, 0x22db, 0x0078, 0x14f3, 0x1078, + 0x22cd, 0x0078, 0x14f3, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1522, + 0xa2a4, 0x00ff, 0x2061, 0x5040, 0x6118, 0xa186, 0x0028, 0x0040, + 0x1509, 0xa186, 0x0032, 0x0040, 0x150f, 0xa186, 0x003c, 0x0040, + 0x1515, 0xa482, 0x0064, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482, + 0x0050, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482, 0x0043, 0x0048, + 0x151f, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a, + 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, + 0x0078, 0x1281, 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a14, + 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, + 0x0078, 0x1281, 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4, + 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x22e9, + 0x0078, 0x1281, 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a08, + 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, + 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, + 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1567, 0x1078, 0x21b1, 0x2091, + 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078, 0x1956, 0x2091, + 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, + 0x157b, 0x1078, 0x21b1, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, + 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, + 0x8000, 0x1078, 0x1963, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, + 0x1282, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, + 0x19c4, 0x00c0, 0x15a9, 0x6818, 0xa005, 0x0040, 0x15a9, 0x2708, + 0x1078, 0x22f9, 0x00c0, 0x15a9, 0x7817, 0x0015, 0x2091, 0x8001, + 0x007c, 0x2091, 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041, + 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, + 0x1963, 0x2061, 0x5040, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f, + 0x6073, 0x0000, 0x7817, 0x0016, 0x1078, 0x21b1, 0x2091, 0x8001, + 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, + 0x8000, 0x2061, 0x5040, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782, + 0x6093, 0x000f, 0x7817, 0x0017, 0x1078, 0x21b1, 0x2091, 0x8001, + 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, + 0x1078, 0x1963, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0, + 0x15e8, 0x2091, 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0, + 0x1618, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, + 0x0008, 0x1078, 0x1956, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, + 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1601, 0xa7bc, + 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1601, + 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, + 0x1641, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, + 0x0040, 0x162e, 0x0070, 0x162e, 0x0078, 0x1625, 0x684b, 0x0009, + 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x163b, 0x0070, + 0x163b, 0x0078, 0x1632, 0x20a9, 0x00fa, 0x0070, 0x1641, 0x0078, + 0x163d, 0x2079, 0x5000, 0x7817, 0x0018, 0x2061, 0x5040, 0x606f, + 0x0001, 0x6073, 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002, + 0x78ce, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091, + 0x8001, 0x007c, 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001, + 0x00c0, 0x1664, 0x1078, 0x1a0e, 0x71c4, 0x71c6, 0x794a, 0x007c, + 0x1078, 0x1b36, 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de, + 0x0078, 0x1675, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc, + 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x5000, 0x2091, 0x8000, 0x1078, + 0x1911, 0x2091, 0x8001, 0x0040, 0x172c, 0x20a9, 0x0005, 0x20a1, + 0x5018, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020, + 0x1078, 0x190c, 0x0040, 0x1698, 0x1078, 0x192b, 0x0078, 0x172c, + 0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16fb, 0x0c7e, + 0x2c68, 0x2091, 0x8000, 0x1078, 0x1911, 0x2091, 0x8001, 0x0040, + 0x16cc, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x16a0, 0x609f, 0x0000, + 0x0c7f, 0x0c7e, 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c, + 0xa065, 0x0040, 0x16fa, 0x2009, 0x0020, 0x1078, 0x190c, 0x00c0, + 0x16e3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16cc, + 0x2d00, 0x6002, 0x0078, 0x16b2, 0x0c7f, 0x0c7e, 0x609c, 0x2060, + 0x1078, 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, + 0x000c, 0x6008, 0xa085, 0x0200, 0x600a, 0x1078, 0x1907, 0x1078, + 0x192b, 0x0078, 0x172c, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, + 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c, + 0x6007, 0x0103, 0x601b, 0x0003, 0x1078, 0x1907, 0x1078, 0x192b, + 0x0078, 0x172c, 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091, + 0x8000, 0x7817, 0x0012, 0x0e7e, 0x2071, 0x5040, 0x706f, 0x0005, + 0x7073, 0x0000, 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000, + 0x2c00, 0x708a, 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2, + 0xa184, 0x0060, 0x0040, 0x171e, 0x1078, 0x467f, 0x0e7f, 0x6596, + 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078, + 0x21b1, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, + 0x20a9, 0x0005, 0x2099, 0x5018, 0x2091, 0x8000, 0x530a, 0x2091, + 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, + 0x0000, 0x007c, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284, + 0x71c4, 0x71c6, 0x2168, 0x0078, 0x174f, 0x2069, 0x1000, 0x690c, + 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1751, 0xa285, + 0x0000, 0x00c0, 0x175f, 0x70c3, 0x4000, 0x0078, 0x1761, 0x70c3, + 0x4003, 0x70ca, 0x0078, 0x1287, 0x2011, 0x5067, 0x220c, 0x70c4, + 0x8003, 0x0048, 0x1771, 0x1078, 0x3b49, 0xa184, 0x7fff, 0x0078, + 0x1775, 0x1078, 0x3b3c, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283, + 0x71c4, 0x1078, 0x3b33, 0x6100, 0x2001, 0x5067, 0x2004, 0xa084, + 0x8000, 0xa10d, 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078, + 0x1283, 0x71c4, 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004, + 0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078, + 0x1284, 0x70c4, 0x2068, 0x2079, 0x5000, 0x2091, 0x8000, 0x1078, + 0x1911, 0x2091, 0x8001, 0x0040, 0x1825, 0x6007, 0x0001, 0x600b, + 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f, + 0xa284, 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, + 0xa284, 0x0800, 0x0040, 0x17c0, 0x601b, 0x000a, 0x0078, 0x17c6, + 0xa284, 0x1000, 0x0040, 0x17c6, 0x601b, 0x000c, 0xa284, 0x0300, + 0x0040, 0x17cf, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, + 0x0001, 0x601e, 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400, + 0x0040, 0x17dc, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, + 0x20a0, 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, + 0x17f1, 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, + 0x17fb, 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, + 0x6552, 0x6596, 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042, + 0x2c08, 0x2061, 0x5040, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077, + 0x0000, 0x607b, 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284, + 0x0400, 0x608e, 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007, + 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000, + 0x1078, 0x21b1, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, + 0x1287, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071, + 0x5040, 0x2079, 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040, + 0x18aa, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1844, + 0xa286, 0x000f, 0x00c0, 0x18aa, 0x691c, 0xa184, 0x0080, 0x00c0, + 0x18aa, 0x6824, 0xa18c, 0xff00, 0xa085, 0x0019, 0x6826, 0x71b0, + 0x81ff, 0x0040, 0x1865, 0x0d7e, 0x2069, 0x0020, 0x6908, 0x6808, + 0xa106, 0x00c0, 0x1856, 0x690c, 0x680c, 0xa106, 0x00c0, 0x185b, + 0xa184, 0x00ff, 0x00c0, 0x185b, 0x0d7f, 0x78b8, 0xa084, 0x801f, + 0x00c0, 0x1865, 0x7848, 0xa085, 0x000c, 0x784a, 0x71b0, 0x81ff, + 0x0040, 0x1888, 0x70b3, 0x0000, 0x0d7e, 0x2069, 0x0020, 0x6807, + 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x1879, 0x6807, 0x0008, + 0x6804, 0xa084, 0x0008, 0x00c0, 0x1880, 0x6807, 0x0002, 0x0d7f, + 0x61c4, 0x62c8, 0x63cc, 0x61c6, 0x62ca, 0x63ce, 0x0e7e, 0x2071, + 0x5000, 0x7266, 0x736a, 0xae80, 0x0019, 0x0e7f, 0x1078, 0x4598, + 0x78a3, 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4, 0xa080, + 0x00da, 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, + 0x0078, 0x1284, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, + 0x2001, 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4, 0xa182, + 0x0003, 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980, 0x71c6, + 0x0078, 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978, 0x71ca, + 0x71c8, 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078, 0x1284, + 0x7974, 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078, 0x1284, + 0x7900, 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004, 0xa082, + 0x0005, 0x0048, 0x18e7, 0x0038, 0x18e9, 0x0078, 0x18f3, 0x00a8, + 0x18f3, 0xa18c, 0x0001, 0x00c0, 0x18f1, 0x20b9, 0x2222, 0x0078, + 0x18f3, 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6, 0x0078, + 0x1284, 0x2009, 0x5074, 0x2104, 0x70c6, 0x70c4, 0x200a, 0x0078, + 0x1284, 0x2009, 0x5074, 0x2104, 0x70c6, 0x0078, 0x1284, 0xac80, + 0x0001, 0x1078, 0x1af2, 0x007c, 0xac80, 0x0001, 0x1078, 0x1a92, + 0x007c, 0x7850, 0xa065, 0x0040, 0x1919, 0x2c04, 0x7852, 0x2063, + 0x0000, 0x007c, 0x0f7e, 0x2079, 0x5000, 0x7850, 0xa06d, 0x0040, + 0x1929, 0x2d04, 0x7852, 0x6803, 0x0000, 0x6807, 0x0000, 0x680b, + 0x0000, 0x0f7f, 0x007c, 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5000, + 0x7850, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1938, 0x1078, 0x23ca, + 0x7852, 0x0f7f, 0x2091, 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5000, + 0x7850, 0x206a, 0x2d00, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7700, + 0x7a52, 0x7bec, 0x8319, 0x0040, 0x1953, 0xa280, 0x0031, 0x2012, + 0x2010, 0x0078, 0x194a, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, + 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, + 0xa0e8, 0x5300, 0x007c, 0x1078, 0x1956, 0x2900, 0x682a, 0x2a00, + 0x682e, 0x6808, 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x5052, + 0x210c, 0x6804, 0xa005, 0x0040, 0x1995, 0xa116, 0x00c0, 0x1980, + 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1983, + 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1992, 0x6000, + 0x6806, 0x1078, 0x19a3, 0x1078, 0x1c42, 0x6810, 0x8001, 0x6812, + 0x00c0, 0x1983, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, + 0x19a2, 0x609c, 0x609f, 0x0000, 0x2008, 0x1078, 0x192b, 0x2100, + 0x0078, 0x1996, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, + 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, + 0x601a, 0x682c, 0x6022, 0x007c, 0x0e7e, 0x2071, 0x5040, 0x704c, + 0xa08c, 0x0200, 0x00c0, 0x19c2, 0xa088, 0x5080, 0x2d0a, 0x8000, + 0x704e, 0xa006, 0x0e7f, 0x007c, 0x1078, 0x1956, 0x2091, 0x8000, + 0x6804, 0x781e, 0xa065, 0x0040, 0x1a0d, 0x0078, 0x19d5, 0x2c00, + 0x781e, 0x6000, 0xa065, 0x0040, 0x1a0d, 0x600c, 0xa306, 0x00c0, + 0x19cf, 0x6010, 0xa206, 0x00c0, 0x19cf, 0x2c28, 0x2001, 0x5052, + 0x2004, 0xac06, 0x00c0, 0x19e6, 0x0078, 0x1a0b, 0x6804, 0xac06, + 0x00c0, 0x19f3, 0x6000, 0xa065, 0x6806, 0x00c0, 0x19fd, 0x6803, + 0x0000, 0x0078, 0x19fd, 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, + 0x0000, 0x00c0, 0x19fd, 0x2c00, 0x6802, 0x2560, 0x1078, 0x19a3, + 0x601b, 0x0005, 0x6023, 0x0020, 0x1078, 0x1c42, 0x6810, 0x8001, + 0x1050, 0x23ca, 0x6812, 0xa085, 0xffff, 0x007c, 0x2039, 0x0000, + 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, + 0x1078, 0x1963, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1a18, 0xa7bc, + 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1a18, + 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, + 0x00c0, 0x1a3c, 0x2091, 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, + 0x8001, 0xa005, 0x00c0, 0x1a3d, 0x007c, 0xa08c, 0xfff0, 0x0040, + 0x1a43, 0x1078, 0x23ca, 0x0079, 0x1a45, 0x1a55, 0x1a58, 0x1a5e, + 0x1a62, 0x1a56, 0x1a66, 0x1a6c, 0x1a56, 0x1a56, 0x1c0c, 0x1c30, + 0x1c34, 0x1a56, 0x1a56, 0x1a56, 0x1a56, 0x007c, 0x1078, 0x23ca, + 0x1078, 0x1a0e, 0x2001, 0x8001, 0x0078, 0x1c3a, 0x2001, 0x8003, + 0x0078, 0x1c3a, 0x2001, 0x8004, 0x0078, 0x1c3a, 0x1078, 0x1a0e, + 0x2001, 0x8006, 0x0078, 0x1c3a, 0x2001, 0x8007, 0x0078, 0x1c3a, + 0x2030, 0x2138, 0xa782, 0x0021, 0x0048, 0x1a78, 0x2009, 0x0020, + 0x2600, 0x1078, 0x1a92, 0x00c0, 0x1a91, 0xa7ba, 0x0020, 0x0048, + 0x1a90, 0x0040, 0x1a90, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1a72, + 0xa006, 0x007c, 0x81ff, 0x0040, 0x1acd, 0x2099, 0x0030, 0x20a0, + 0x700c, 0xa084, 0x00ff, 0x0040, 0x1aa4, 0x7007, 0x0004, 0x7004, + 0xa084, 0x0004, 0x00c0, 0x1a9f, 0x21a8, 0x7017, 0x0000, 0x810b, + 0x7112, 0x721a, 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0001, + 0x7002, 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, + 0x00c8, 0x1ac1, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, + 0x1ab3, 0x7008, 0x800b, 0x00c8, 0x1ab3, 0x7007, 0x0002, 0xa08c, + 0x01e0, 0x00c0, 0x1acd, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, + 0x2030, 0x2138, 0xa782, 0x0021, 0x0048, 0x1ad8, 0x2009, 0x0020, + 0x2600, 0x1078, 0x1af2, 0x00c0, 0x1af1, 0xa7ba, 0x0020, 0x0048, + 0x1af0, 0x0040, 0x1af0, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1ad2, + 0xa006, 0x007c, 0x81ff, 0x0040, 0x1b33, 0x2098, 0x20a1, 0x0030, + 0x700c, 0xa084, 0x00ff, 0x0040, 0x1b04, 0x7007, 0x0004, 0x7004, + 0xa084, 0x0004, 0x00c0, 0x1aff, 0x21a8, 0x7017, 0x0000, 0x810b, + 0x7112, 0x721a, 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0000, + 0x7002, 0x53a6, 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, + 0x0005, 0x00c8, 0x1b22, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, + 0x00c0, 0x1b14, 0x7010, 0xa084, 0xf000, 0x0040, 0x1b2b, 0x7007, + 0x0008, 0x0078, 0x1b2f, 0x7108, 0x8103, 0x00c8, 0x1b14, 0x7007, + 0x0002, 0xa184, 0x01e0, 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, + 0x2004, 0xa082, 0x0004, 0x00c8, 0x1b3f, 0x0078, 0x1b42, 0xa006, + 0x0078, 0x1b44, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5000, + 0x2d08, 0x7058, 0x6802, 0xa005, 0x00c0, 0x1b4f, 0x715e, 0x715a, + 0x0e7f, 0x007c, 0x2c08, 0x7858, 0x6002, 0xa005, 0x00c0, 0x1b59, + 0x795e, 0x795a, 0x007c, 0x2091, 0x8000, 0x6003, 0x0000, 0x2c08, + 0x785c, 0xa065, 0x00c0, 0x1b67, 0x795a, 0x0078, 0x1b68, 0x6102, + 0x795e, 0x2091, 0x8001, 0x1078, 0x21ce, 0x007c, 0x0e7e, 0x2071, + 0x5000, 0x7058, 0xa06d, 0x0040, 0x1b7c, 0x6800, 0x705a, 0xa005, + 0x00c0, 0x1b7b, 0x705e, 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, + 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, + 0x0040, 0x1bac, 0x2068, 0x6814, 0xa306, 0x00c0, 0x1b95, 0x6828, + 0xa084, 0x00ff, 0xa406, 0x0040, 0x1b98, 0x2d60, 0x0078, 0x1b86, + 0x6800, 0xa005, 0x6002, 0x00c0, 0x1ba4, 0xaf80, 0x0016, 0xac06, + 0x0040, 0x1ba3, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040, + 0x1bab, 0x1078, 0x1996, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, + 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016, + 0x2060, 0x6000, 0xa005, 0x0040, 0x1bdb, 0x2068, 0x6814, 0xa084, + 0x00ff, 0xa306, 0x0040, 0x1bc7, 0x2d60, 0x0078, 0x1bb9, 0x6800, + 0xa005, 0x6002, 0x00c0, 0x1bd3, 0xaf80, 0x0016, 0xac06, 0x0040, + 0x1bd2, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bda, + 0x1078, 0x1996, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, + 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016, 0x2060, + 0x6000, 0xa06d, 0x0040, 0x1c07, 0x6814, 0xa306, 0x0040, 0x1bf3, + 0x2d60, 0x0078, 0x1be8, 0x6800, 0xa005, 0x6002, 0x00c0, 0x1bff, + 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bfe, 0x2c00, 0x785e, 0x0d7e, + 0x689c, 0xa005, 0x0040, 0x1c06, 0x1078, 0x1996, 0x007f, 0x0f7f, + 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x2091, 0x8000, 0x2069, 0x5040, + 0x6800, 0xa086, 0x0000, 0x0040, 0x1c1a, 0x2091, 0x8001, 0x78e3, + 0x0009, 0x007c, 0x6880, 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, + 0x0004, 0x2051, 0x0010, 0x1078, 0x1963, 0x8738, 0xa784, 0x001f, + 0x00c0, 0x1c23, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078, 0x1c3a, + 0x2001, 0x800c, 0x0078, 0x1c3a, 0x1078, 0x1a0e, 0x2001, 0x800d, + 0x0078, 0x1c3a, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, + 0x4080, 0x007c, 0x6004, 0x2c08, 0x2063, 0x0000, 0x7884, 0x8000, + 0x7886, 0x7888, 0xa005, 0x798a, 0x0040, 0x1c51, 0x2c02, 0x0078, + 0x1c52, 0x798e, 0x007c, 0x6807, 0x0103, 0x0c7e, 0x2061, 0x5000, + 0x2d08, 0x206b, 0x0000, 0x6084, 0x8000, 0x6086, 0x6088, 0xa005, + 0x618a, 0x0040, 0x1c66, 0x2d02, 0x0078, 0x1c67, 0x618e, 0x0c7f, + 0x007c, 0x1078, 0x1c7a, 0x0040, 0x1c79, 0x0c7e, 0x609c, 0xa065, + 0x0040, 0x1c74, 0x1078, 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078, + 0x192b, 0x007c, 0x788c, 0xa065, 0x0040, 0x1c8c, 0x2091, 0x8000, + 0x7884, 0x8001, 0x7886, 0x2c04, 0x788e, 0xa005, 0x00c0, 0x1c8a, + 0x788a, 0x8000, 0x2091, 0x8001, 0x007c, 0x20a9, 0x0010, 0xa006, + 0x8004, 0x8086, 0x818e, 0x00c8, 0x1c96, 0xa200, 0x0070, 0x1c9a, + 0x0078, 0x1c91, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, + 0xa005, 0x0040, 0x1cc0, 0xa11a, 0x00c8, 0x1cc0, 0x8213, 0x818d, + 0x0048, 0x1cb1, 0xa11a, 0x00c8, 0x1cb2, 0x0070, 0x1cb8, 0x0078, + 0x1ca6, 0xa11a, 0x2308, 0x8210, 0x0070, 0x1cb8, 0x0078, 0x1ca6, + 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, + 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x1cbc, 0x7994, 0x70d0, + 0xa106, 0x0040, 0x1d34, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, + 0xa005, 0x00c0, 0x1d34, 0x7008, 0x7208, 0xa206, 0x00c0, 0x1d34, + 0xa286, 0x0008, 0x00c0, 0x1d34, 0x2071, 0x0010, 0x1078, 0x1911, + 0x0040, 0x1d34, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa184, 0xff00, + 0x0040, 0x1d02, 0x2031, 0x0000, 0x810b, 0x86b5, 0x810b, 0x86b5, + 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, + 0x2100, 0xa210, 0x2600, 0xa319, 0xa4a1, 0x0000, 0xa5a9, 0x0000, + 0x0078, 0x1d0c, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, + 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x2009, 0x0020, 0x1078, 0x190c, + 0x2091, 0x8001, 0x0040, 0x1d2b, 0x1078, 0x192b, 0x78a8, 0x8000, + 0x78aa, 0xa086, 0x0002, 0x00c0, 0x1d34, 0x2091, 0x8000, 0x78e3, + 0x0002, 0x78ab, 0x0000, 0x78cc, 0xa085, 0x0003, 0x78ce, 0x2091, + 0x8001, 0x0078, 0x1d34, 0x78ab, 0x0000, 0x1078, 0x208b, 0x6004, + 0xa084, 0x000f, 0x0079, 0x1d39, 0x2071, 0x0010, 0x2091, 0x8001, + 0x007c, 0x1d49, 0x1d6b, 0x1d91, 0x1d49, 0x1dae, 0x1d58, 0x1f0d, + 0x1f28, 0x1d49, 0x1d65, 0x1d8b, 0x1df6, 0x1e63, 0x1eb3, 0x1ec5, + 0x1f24, 0x2039, 0x0400, 0x78dc, 0xa705, 0x78de, 0x6008, 0xa705, + 0x600a, 0x1078, 0x1fa6, 0x609c, 0x78da, 0x1078, 0x2073, 0x007c, + 0x78dc, 0xa084, 0x0100, 0x0040, 0x1d5f, 0x0078, 0x1d49, 0x601c, + 0xa085, 0x0080, 0x601e, 0x0078, 0x1d72, 0x1078, 0x1b36, 0x00c0, + 0x1d49, 0x1078, 0x20a5, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1d72, + 0x0078, 0x1d49, 0x78df, 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, + 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x1d88, 0x1078, 0x1fa6, + 0x0040, 0x1d88, 0x78dc, 0xa085, 0x0100, 0x78de, 0x0078, 0x1d8a, + 0x1078, 0x1fca, 0x007c, 0x1078, 0x1b36, 0x00c0, 0x1d49, 0x1078, + 0x20a1, 0x78dc, 0xa08c, 0x0e00, 0x00c0, 0x1d9a, 0xa084, 0x0100, + 0x00c0, 0x1d9c, 0x0078, 0x1d49, 0x1078, 0x1fa6, 0x00c0, 0x1dad, + 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x1f63, 0xa186, + 0x000f, 0x0040, 0x1f63, 0x1078, 0x1fca, 0x007c, 0x78dc, 0xa084, + 0x0100, 0x0040, 0x1db5, 0x0078, 0x1d49, 0x78df, 0x0000, 0x6714, + 0x2011, 0x0001, 0x20a9, 0x0001, 0x6018, 0xa084, 0x00ff, 0xa005, + 0x0040, 0x1dd8, 0x2011, 0x0001, 0xa7bc, 0xff00, 0x20a9, 0x0020, + 0xa08e, 0x0001, 0x0040, 0x1dd8, 0x2039, 0x0000, 0x2011, 0x0002, + 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, 0x1dd8, 0x0078, 0x1df3, + 0x1078, 0x1956, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, + 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, + 0x0070, 0x1dec, 0x0078, 0x1dda, 0x8211, 0x0040, 0x1df3, 0x20a9, + 0x0100, 0x0078, 0x1dda, 0x1078, 0x192b, 0x007c, 0x2001, 0x5067, + 0x2004, 0xa084, 0x8000, 0x0040, 0x1f8b, 0x6114, 0x1078, 0x20c2, + 0x6900, 0xa184, 0x0001, 0x0040, 0x1e17, 0x6028, 0xa084, 0x00ff, + 0x00c0, 0x1f83, 0x6800, 0xa084, 0x0001, 0x0040, 0x1f8b, 0x6803, + 0x0000, 0x680b, 0x0000, 0x6807, 0x0000, 0x0078, 0x1f93, 0x2011, + 0x0001, 0x6020, 0xa084, 0x4000, 0x0040, 0x1e20, 0xa295, 0x0002, + 0x6020, 0xa084, 0x0100, 0x0040, 0x1e27, 0xa295, 0x0008, 0x601c, + 0xa084, 0x0002, 0x0040, 0x1e2e, 0xa295, 0x0004, 0x602c, 0xa08c, + 0x00ff, 0xa182, 0x0002, 0x0048, 0x1f8f, 0xa182, 0x001b, 0x00c8, + 0x1f8f, 0x0040, 0x1f8f, 0x690e, 0x602c, 0x8007, 0xa08c, 0x00ff, + 0xa182, 0x0002, 0x0048, 0x1f8f, 0xa182, 0x001b, 0x00c8, 0x1f8f, + 0x0040, 0x1f8f, 0x6912, 0x6030, 0xa005, 0x00c0, 0x1e51, 0x2001, + 0x001e, 0x8000, 0x6816, 0x6028, 0xa084, 0x00ff, 0x0040, 0x1f8b, + 0x6806, 0x6028, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1f8b, 0x680a, + 0x6a02, 0x0078, 0x1f93, 0x2001, 0x5067, 0x2004, 0xa084, 0x8000, + 0x0040, 0x1f8b, 0x6114, 0x1078, 0x20c2, 0x2091, 0x8000, 0x6a04, + 0x6b08, 0x6418, 0xa484, 0x0003, 0x0040, 0x1e89, 0x6128, 0xa18c, + 0x00ff, 0x8001, 0x00c0, 0x1e82, 0x2100, 0xa210, 0x0048, 0x1eaf, + 0x0078, 0x1e89, 0x8001, 0x00c0, 0x1eaf, 0x2100, 0xa212, 0x0048, + 0x1eaf, 0xa484, 0x000c, 0x0040, 0x1ea3, 0x6128, 0x810f, 0xa18c, + 0x00ff, 0xa082, 0x0004, 0x00c0, 0x1e9b, 0x2100, 0xa318, 0x0048, + 0x1eaf, 0x0078, 0x1ea3, 0xa082, 0x0004, 0x00c0, 0x1eaf, 0x2100, + 0xa31a, 0x0048, 0x1eaf, 0x6030, 0xa005, 0x0040, 0x1ea9, 0x8000, + 0x6816, 0x6a06, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1f93, 0x2091, + 0x8001, 0x0078, 0x1f8f, 0x6114, 0x1078, 0x20c2, 0x2091, 0x8000, + 0x6b08, 0x8318, 0x0048, 0x1ec1, 0x6b0a, 0x2091, 0x8001, 0x0078, + 0x1fa2, 0x2091, 0x8001, 0x0078, 0x1f8f, 0x6024, 0x8007, 0xa084, + 0x00ff, 0x0040, 0x1ee3, 0xa086, 0x0080, 0x00c0, 0x1f0b, 0x20a9, + 0x0008, 0x2069, 0x7410, 0x2091, 0x8000, 0x6800, 0xa084, 0xfcff, + 0x6802, 0xade8, 0x0008, 0x0070, 0x1edf, 0x0078, 0x1ed5, 0x2091, + 0x8001, 0x0078, 0x1f93, 0x6028, 0xa015, 0x0040, 0x1f0b, 0x6114, + 0x1078, 0x20c2, 0x0d7e, 0xade8, 0x0007, 0x2091, 0x8000, 0x6800, + 0xa00d, 0x0040, 0x1f08, 0xa206, 0x0040, 0x1ef9, 0x2168, 0x0078, + 0x1eef, 0x0c7e, 0x2160, 0x6000, 0x6802, 0x1078, 0x192b, 0x0c7f, + 0x0d7f, 0x6808, 0x8000, 0x680a, 0x2091, 0x8001, 0x0078, 0x1fa2, + 0x2091, 0x8001, 0x0d7f, 0x0078, 0x1f8b, 0x6114, 0x1078, 0x20c2, + 0x6800, 0xa084, 0x0001, 0x0040, 0x1f7b, 0x2091, 0x8000, 0x6a04, + 0x8210, 0x0048, 0x1f20, 0x6a06, 0x2091, 0x8001, 0x0078, 0x1fa2, + 0x2091, 0x8001, 0x0078, 0x1f8f, 0x1078, 0x1b36, 0x00c0, 0x1d49, + 0x6114, 0x1078, 0x20c2, 0x60be, 0x6900, 0xa184, 0x0008, 0x0040, + 0x1f35, 0x6020, 0xa085, 0x0100, 0x6022, 0xa184, 0x0001, 0x0040, + 0x1f8b, 0xa184, 0x0100, 0x00c0, 0x1f77, 0xa184, 0x0200, 0x00c0, + 0x1f73, 0x681c, 0xa005, 0x00c0, 0x1f7f, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x000f, 0x00c0, 0x1f4e, 0x1078, 0x20a5, 0x78df, 0x0000, + 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, + 0x0040, 0x1f63, 0x1078, 0x1fa6, 0x0040, 0x1f63, 0x78dc, 0xa085, + 0x0100, 0x78de, 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000, 0x6024, + 0xa084, 0xff00, 0x6026, 0x1078, 0x39aa, 0x0040, 0x1cc6, 0x1078, + 0x1b5b, 0x0078, 0x1cc6, 0x2009, 0x0017, 0x0078, 0x1f95, 0x2009, + 0x000e, 0x0078, 0x1f95, 0x2009, 0x0007, 0x0078, 0x1f95, 0x2009, + 0x0035, 0x0078, 0x1f95, 0x2009, 0x003e, 0x0078, 0x1f95, 0x2009, + 0x0004, 0x0078, 0x1f95, 0x2009, 0x0006, 0x0078, 0x1f95, 0x2009, + 0x0016, 0x0078, 0x1f95, 0x2009, 0x0001, 0x6024, 0xa084, 0xff00, + 0xa105, 0x6026, 0x2091, 0x8000, 0x1078, 0x1c42, 0x2091, 0x8001, + 0x0078, 0x1cc6, 0x1078, 0x192b, 0x0078, 0x1cc6, 0x78d4, 0xa06d, + 0x00c0, 0x1fb1, 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000, 0x0078, + 0x1fbd, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00, 0x6002, + 0x78d8, 0xad06, 0x00c0, 0x1fbd, 0x6002, 0x78d0, 0x8001, 0x78d2, + 0x00c0, 0x1fc9, 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8, 0x2060, + 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xe1ff, + 0x601e, 0xa184, 0x0060, 0x0040, 0x1fd9, 0x0e7e, 0x1078, 0x467f, + 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, + 0x0000, 0x6714, 0x1078, 0x1956, 0x2091, 0x8000, 0x60a0, 0xa084, + 0x8000, 0x00c0, 0x2000, 0x6808, 0xa084, 0x0001, 0x0040, 0x2000, + 0x2091, 0x8001, 0x1078, 0x19a3, 0x2091, 0x8000, 0x1078, 0x1c42, + 0x2091, 0x8001, 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078, 0x2072, + 0x6024, 0xa096, 0x0001, 0x00c0, 0x2007, 0x8000, 0x6026, 0x6a10, + 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x2016, 0x0040, 0x2016, + 0x2039, 0x0200, 0x1078, 0x2073, 0x0078, 0x2072, 0x2c08, 0x2091, + 0x8000, 0x60a0, 0xa084, 0x8000, 0x0040, 0x2043, 0x6800, 0xa065, + 0x0040, 0x2048, 0x6a04, 0x0e7e, 0x2071, 0x5040, 0x7000, 0xa084, + 0x0001, 0x0040, 0x203d, 0x7048, 0xa206, 0x00c0, 0x203d, 0x6b04, + 0x231c, 0x2160, 0x6302, 0x2300, 0xa005, 0x00c0, 0x2038, 0x6902, + 0x2260, 0x6102, 0x0e7f, 0x0078, 0x204f, 0x2160, 0x6202, 0x6906, + 0x0e7f, 0x0078, 0x204f, 0x6800, 0xa065, 0x0040, 0x2048, 0x6102, + 0x6902, 0x00c0, 0x204c, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, + 0x60a0, 0xa084, 0x8000, 0x0040, 0x2059, 0x6808, 0xa084, 0xfffc, + 0x680a, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, + 0x0040, 0x0040, 0x2068, 0xa086, 0x0040, 0x680a, 0x1078, 0x19b4, + 0x2091, 0x8000, 0x1078, 0x21b1, 0x2091, 0x8001, 0x78db, 0x0000, + 0x78d7, 0x0000, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, + 0x1078, 0x1c42, 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040, 0x2086, + 0x609c, 0x78da, 0x609f, 0x0000, 0x0078, 0x2076, 0x78d7, 0x0000, + 0x78db, 0x0000, 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, + 0x2092, 0xa006, 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040, 0x20a0, + 0x8001, 0x7806, 0x00c0, 0x20a0, 0x0068, 0x20a0, 0x2091, 0x4080, + 0x007c, 0x2039, 0x20b9, 0x0078, 0x20a7, 0x2039, 0x20bf, 0x2704, + 0xa005, 0x0040, 0x20b8, 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, + 0x6a14, 0x690a, 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078, 0x20a7, + 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, + 0x001b, 0x0000, 0x0c7e, 0x1078, 0x3b33, 0x2c68, 0x0c7f, 0x007c, + 0x0010, 0x2139, 0x0068, 0x2139, 0x2029, 0x0000, 0x78cb, 0x0000, + 0x788c, 0xa065, 0x0040, 0x2132, 0x2009, 0x5074, 0x2104, 0xa084, + 0x0001, 0x0040, 0x2100, 0x6004, 0xa086, 0x0103, 0x00c0, 0x2100, + 0x6018, 0xa005, 0x00c0, 0x2100, 0x6014, 0xa005, 0x00c0, 0x2100, + 0x0d7e, 0x2069, 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0, 0x20ff, + 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, + 0x2091, 0x4080, 0x0d7f, 0x1078, 0x1c69, 0x0078, 0x2137, 0x0d7f, + 0x1078, 0x213a, 0x0040, 0x2132, 0x6204, 0xa294, 0x00ff, 0xa296, + 0x0003, 0x0040, 0x2112, 0x6204, 0xa296, 0x0110, 0x00c0, 0x2120, + 0x78cb, 0x0001, 0x6204, 0xa294, 0xff00, 0x8217, 0x8211, 0x0040, + 0x2120, 0x85ff, 0x00c0, 0x2132, 0x8210, 0xa202, 0x00c8, 0x2132, + 0x057e, 0x1078, 0x2149, 0x057f, 0x0040, 0x212d, 0x78e0, 0xa086, + 0x0003, 0x0040, 0x2132, 0x0078, 0x2120, 0x8528, 0x78c8, 0xa005, + 0x0040, 0x20d0, 0x85ff, 0x0040, 0x2139, 0x2091, 0x4080, 0x78b0, + 0x70d6, 0x007c, 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0, 0x2143, + 0x2300, 0xa005, 0x007c, 0x0048, 0x2147, 0xa302, 0x007c, 0x8002, + 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x2163, + 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2198, + 0x7008, 0x7208, 0xa206, 0x00c0, 0x2198, 0xa286, 0x0008, 0x00c0, + 0x2198, 0x2071, 0x0010, 0x1078, 0x219d, 0x2009, 0x0020, 0x6004, + 0xa086, 0x0103, 0x00c0, 0x2172, 0x6028, 0xa005, 0x00c0, 0x2172, + 0x2009, 0x000c, 0x1078, 0x1907, 0x0040, 0x218b, 0x78c4, 0x8000, + 0x78c6, 0xa086, 0x0002, 0x00c0, 0x2198, 0x2091, 0x8000, 0x78e3, + 0x0003, 0x78c7, 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce, 0x2091, + 0x8001, 0x0078, 0x2198, 0x78c7, 0x0000, 0x1078, 0x1c69, 0x79ac, + 0x78b0, 0x8000, 0xa10a, 0x00c8, 0x2196, 0xa006, 0x78b2, 0xa006, + 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, + 0x7ab8, 0x7bb4, 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000, 0xa4a1, + 0x0000, 0xa5a9, 0x0000, 0x007c, 0x2009, 0x505b, 0x2091, 0x8000, + 0x200a, 0x0f7e, 0x0e7e, 0x2071, 0x5040, 0x7000, 0xa086, 0x0000, + 0x00c0, 0x21cb, 0x2009, 0x5012, 0x2104, 0xa005, 0x00c0, 0x21cb, + 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21cb, 0x0018, + 0x21cb, 0x781b, 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, + 0x2071, 0x5040, 0x2091, 0x8000, 0x7000, 0xa086, 0x0000, 0x00c0, + 0x21e4, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21e4, + 0x0018, 0x21e4, 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f, 0x0f7f, + 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x5040, 0x2079, 0x0100, + 0x784b, 0x000f, 0x0098, 0x21f7, 0x7838, 0x0078, 0x21f0, 0x20a9, + 0x0040, 0x7800, 0xa082, 0x0004, 0x0048, 0x2200, 0x20a9, 0x0060, + 0x789b, 0x0000, 0x78af, 0x0000, 0x78af, 0x0000, 0x0070, 0x220a, + 0x0078, 0x2202, 0x7800, 0xa082, 0x0004, 0x0048, 0x2219, 0x70b7, + 0x009b, 0x2019, 0x4da4, 0x1078, 0x2255, 0x702f, 0x8001, 0x0078, + 0x2225, 0x70b7, 0x0000, 0x2019, 0x4c1c, 0x1078, 0x2255, 0x2019, + 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x7003, 0x0000, 0x1078, + 0x235e, 0x7004, 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd, 0x210c, + 0xa18a, 0x0005, 0x0048, 0x223a, 0x0038, 0x2240, 0xa085, 0x6280, + 0x0078, 0x2242, 0x0028, 0x2240, 0xa085, 0x6280, 0x0078, 0x2242, + 0xa085, 0x62c0, 0x017f, 0x7806, 0x780f, 0xb204, 0x7843, 0x00d8, + 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x0008, 0x7053, 0x507f, + 0x704f, 0x0000, 0x127f, 0x2000, 0x007c, 0x137e, 0x147e, 0x157e, + 0x047e, 0x20a1, 0x012b, 0x2304, 0xa005, 0x789a, 0x0040, 0x2275, + 0x8318, 0x2324, 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00, 0x0040, + 0x226d, 0xa482, 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6, 0xa005, + 0x00c0, 0x2264, 0x3318, 0x0078, 0x225b, 0x047f, 0x157f, 0x147f, + 0x137f, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, + 0xfff0, 0xa105, 0x2012, 0x1078, 0x235e, 0x007c, 0x2011, 0x0101, + 0x20a9, 0x0009, 0x810b, 0x0070, 0x228f, 0x0078, 0x228a, 0xa18c, + 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, + 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x22a0, 0x0078, 0x229b, + 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, + 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, 0x22b1, 0x0078, + 0x22ac, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, + 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, + 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, + 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, + 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, + 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, + 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, + 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, + 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, + 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, + 0x233c, 0x2061, 0x7400, 0x1078, 0x2344, 0x0040, 0x2328, 0x20a9, + 0x0000, 0x2061, 0x7300, 0x0c7e, 0x1078, 0x2344, 0x0040, 0x2318, + 0x0c7f, 0x8c60, 0x0070, 0x2316, 0x0078, 0x230b, 0x0078, 0x233c, + 0x007f, 0xa082, 0x7300, 0x2071, 0x5040, 0x7086, 0x7182, 0x2001, + 0x0004, 0x706e, 0x7093, 0x000f, 0x1078, 0x21ac, 0x0078, 0x2338, + 0x60c0, 0xa005, 0x00c0, 0x233c, 0x2071, 0x5040, 0x7182, 0x2c00, + 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x1078, 0x21ac, + 0x2001, 0x0000, 0x0078, 0x233e, 0x2001, 0x0001, 0x2091, 0x8001, + 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x235b, + 0x2060, 0x600c, 0xa306, 0x00c0, 0x2358, 0x6010, 0xa206, 0x00c0, + 0x2358, 0x6014, 0xa106, 0x00c0, 0x2358, 0xa006, 0x0078, 0x235d, + 0x6000, 0x0078, 0x2345, 0xa085, 0x0001, 0x007c, 0x2011, 0x5041, + 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, + 0x0040, 0x2374, 0x2021, 0xff04, 0x2122, 0x810b, 0x810b, 0x810b, + 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e, 0x68e4, 0xa08c, + 0x0020, 0x0040, 0x23c8, 0xa084, 0x0006, 0x00c0, 0x23c8, 0x6014, + 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0, 0x5280, + 0x7004, 0xa084, 0x000a, 0x00c0, 0x23c8, 0x7108, 0xa194, 0xff00, + 0x0040, 0x23c8, 0xa18c, 0x00ff, 0x2001, 0x000c, 0xa106, 0x0040, + 0x23af, 0x2001, 0x0012, 0xa106, 0x0040, 0x23b3, 0x2001, 0x0014, + 0xa106, 0x0040, 0x23b7, 0x2001, 0x0019, 0xa106, 0x0040, 0x23bb, + 0x2001, 0x0032, 0xa106, 0x0040, 0x23bf, 0x0078, 0x23c3, 0x2009, + 0x0012, 0x0078, 0x23c5, 0x2009, 0x0014, 0x0078, 0x23c5, 0x2009, + 0x0019, 0x0078, 0x23c5, 0x2009, 0x0020, 0x0078, 0x23c5, 0x2009, + 0x003f, 0x0078, 0x23c5, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, + 0x0e7f, 0x007c, 0x0068, 0x23ca, 0x2091, 0x8000, 0x2071, 0x0000, + 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x23d1, 0x007f, 0x2071, + 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x073f, + 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0078, 0x23e8, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300, 0x7f3c, + 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca, 0x75ce, 0xa594, + 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079, 0x23ff, 0x2411, + 0x2411, 0x2411, 0x274b, 0x3907, 0x240f, 0x2440, 0x244a, 0x240f, + 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x1078, + 0x23ca, 0x8507, 0xa084, 0x001f, 0x0079, 0x2416, 0x2454, 0x274b, + 0x2905, 0x2a02, 0x2a2a, 0x2cc3, 0x2f6e, 0x2fb1, 0x2ffc, 0x3081, + 0x3139, 0x31e2, 0x2440, 0x2827, 0x2f43, 0x2436, 0x3c78, 0x3c98, + 0x3e5e, 0x3e6a, 0x3f3f, 0x2436, 0x2436, 0x4012, 0x4016, 0x3c76, + 0x2436, 0x3dc9, 0x2436, 0x3b56, 0x244a, 0x2436, 0x1078, 0x23ca, + 0x0018, 0x23ef, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, + 0x2019, 0x4cfd, 0x1078, 0x2255, 0x702f, 0x0001, 0x781b, 0x004f, + 0x0078, 0x2438, 0x2019, 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, + 0x781b, 0x00d5, 0x0078, 0x2438, 0x7242, 0x2009, 0x500f, 0x200b, + 0x0000, 0xa584, 0x0001, 0x00c0, 0x3b6a, 0x0040, 0x2471, 0x1078, + 0x23ca, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043, 0x0000, 0x7037, + 0x0000, 0x1078, 0x38de, 0x0018, 0x23ef, 0x2009, 0x500f, 0x200b, + 0x0000, 0x7068, 0xa005, 0x00c0, 0x253c, 0x706c, 0xa084, 0x0007, + 0x0079, 0x247a, 0x2573, 0x2482, 0x248e, 0x24ab, 0x24cd, 0x251a, + 0x24f3, 0x2482, 0x1078, 0x38c6, 0x2009, 0x0048, 0x1078, 0x2e0f, + 0x00c0, 0x248c, 0x7003, 0x0004, 0x0078, 0x2438, 0x1078, 0x38c6, + 0x00c0, 0x24a9, 0x7080, 0x8007, 0x7882, 0x789b, 0x0010, 0x78ab, + 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, + 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24a9, 0x7003, 0x0004, 0x7093, + 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x24cb, 0x7180, + 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d, 0x00c0, + 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, + 0x0004, 0x2009, 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24cb, 0x7003, + 0x0004, 0x7093, 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, + 0x24f1, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, + 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184, 0x79aa, 0x78ab, + 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, + 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24f1, 0x7003, 0x0004, 0x7093, + 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x2518, 0x7180, + 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d, 0x00c0, + 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, + 0x0004, 0x2009, 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x2518, 0x7088, + 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002, 0x7093, 0x000f, + 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x2438, 0x7088, 0x2068, + 0x6f14, 0x1078, 0x37bd, 0x2c50, 0x1078, 0x3978, 0x789b, 0x0010, + 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x6e1c, 0x2041, + 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004, 0x0040, 0x253a, + 0x2001, 0x0006, 0x0078, 0x265b, 0x1078, 0x38c6, 0x00c0, 0x2438, + 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078, 0x37bd, 0x2c50, + 0x1078, 0x3978, 0x6008, 0xa085, 0x0010, 0x600a, 0x6824, 0xa005, + 0x0040, 0x255a, 0xa082, 0x0006, 0x0048, 0x2558, 0x0078, 0x255a, + 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0x7058, + 0xa084, 0x8000, 0x0040, 0x2568, 0xa684, 0x0001, 0x0040, 0x256a, + 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, + 0x0003, 0x0078, 0x265b, 0x0018, 0x23ef, 0x744c, 0xa485, 0x0000, + 0x0040, 0x258d, 0xa080, 0x5080, 0x2030, 0x7150, 0x8108, 0xa12a, + 0x0048, 0x2584, 0x2009, 0x5080, 0x2164, 0x6504, 0x85ff, 0x00c0, + 0x259e, 0x8421, 0x00c0, 0x257e, 0x7152, 0x7003, 0x0000, 0x704b, + 0x0000, 0x7040, 0xa005, 0x0040, 0x3b6a, 0x0078, 0x2438, 0x764c, + 0xa6b0, 0x5080, 0x7150, 0x2600, 0x0078, 0x2589, 0x7152, 0x2568, + 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0, 0x259b, + 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x25d4, 0xa784, 0x0021, + 0x00c0, 0x259b, 0xa784, 0x0002, 0x0040, 0x25bd, 0xa784, 0x0004, + 0x0040, 0x259b, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, 0x00c0, + 0x259b, 0xa784, 0x0010, 0x00c0, 0x259b, 0xa784, 0x0200, 0x00c0, + 0x259b, 0xa784, 0x0100, 0x0040, 0x25d4, 0x6018, 0xa005, 0x00c0, + 0x259b, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000, 0x6e1c, 0xa684, + 0x000e, 0x6118, 0x0040, 0x25e4, 0x601c, 0xa102, 0x0048, 0x25e7, + 0x0040, 0x25e7, 0x0078, 0x2597, 0x81ff, 0x00c0, 0x2597, 0x68c3, + 0x0000, 0xa784, 0x0080, 0x00c0, 0x25ef, 0x700c, 0x6022, 0xa7bc, + 0xff7f, 0x670a, 0x1078, 0x3978, 0x0018, 0x23ef, 0x789b, 0x0010, + 0xa046, 0x1078, 0x38c6, 0x00c0, 0x2438, 0x6b14, 0xa39c, 0x001f, + 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x260b, 0xa684, + 0x0001, 0x0040, 0x260d, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040, + 0x2613, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0, + 0x261e, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x2659, 0x7158, 0xa18c, + 0x0800, 0x0040, 0x33d7, 0x2011, 0x0020, 0xa684, 0x0008, 0x00c0, + 0x262f, 0x8210, 0xa684, 0x0002, 0x00c0, 0x262f, 0x8210, 0x7aaa, + 0x8840, 0x1078, 0x38de, 0x6a14, 0x610c, 0x8108, 0xa18c, 0x00ff, + 0xa1e0, 0x7300, 0x2c64, 0x8cff, 0x0040, 0x2650, 0x6014, 0xa206, + 0x00c0, 0x263a, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2635, 0x0c7e, + 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x2573, + 0x1078, 0x38c6, 0x00c0, 0x2438, 0x2a60, 0x610e, 0x79aa, 0x8840, + 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184, 0x0018, 0x0040, + 0x2676, 0xa184, 0x0010, 0x0040, 0x2669, 0x1078, 0x35d6, 0x00c0, + 0x2699, 0xa184, 0x0008, 0x0040, 0x2676, 0x69a0, 0xa184, 0x0600, + 0x00c0, 0x2676, 0x1078, 0x34c7, 0x0078, 0x2699, 0x69a0, 0xa184, + 0x0800, 0x0040, 0x268d, 0x0c7e, 0x027e, 0x2960, 0x6000, 0xa085, + 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f, 0x0c7f, + 0x1078, 0x35d6, 0x00c0, 0x2699, 0x69a0, 0xa184, 0x0200, 0x0040, + 0x2695, 0x1078, 0x3516, 0x0078, 0x2699, 0xa184, 0x0400, 0x00c0, + 0x2672, 0x69a0, 0xa184, 0x1000, 0x0040, 0x26a4, 0x6914, 0xa18c, + 0xff00, 0x810f, 0x1078, 0x22cd, 0x007f, 0x7002, 0xa68c, 0x00e0, + 0xa684, 0x0060, 0x0040, 0x26b2, 0xa086, 0x0060, 0x00c0, 0x26b2, + 0xa18d, 0x4000, 0x88ff, 0x0040, 0x26b7, 0xa18d, 0x0004, 0x795a, + 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6818, + 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080, 0x0040, + 0x26d6, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050, 0x26d4, 0xa08a, + 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x78aa, 0x8008, + 0x810c, 0x0040, 0x33dd, 0xa18c, 0x00f8, 0x00c0, 0x33dd, 0x157e, + 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, + 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, + 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2, 0x7eda, + 0x1078, 0x38c6, 0x00c0, 0x270d, 0x702c, 0x8003, 0x0048, 0x2706, + 0x2019, 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x7830, 0xa084, + 0x00c0, 0x00c0, 0x270d, 0x0098, 0x2715, 0x6008, 0xa084, 0xffef, + 0x600a, 0x1078, 0x38de, 0x0078, 0x2461, 0x7200, 0xa284, 0x0007, + 0xa086, 0x0001, 0x00c0, 0x2722, 0x781b, 0x004f, 0x1078, 0x38de, + 0x0078, 0x2733, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x004f, + 0x1078, 0x38de, 0x7200, 0x2500, 0xa605, 0x0040, 0x2733, 0xa284, + 0x0007, 0x1079, 0x2741, 0xad80, 0x0009, 0x7036, 0xa284, 0x0007, + 0xa086, 0x0001, 0x00c0, 0x2438, 0x6018, 0x8000, 0x601a, 0x0078, + 0x2438, 0x2749, 0x48f7, 0x48f7, 0x48e6, 0x48f7, 0x2749, 0x48e6, + 0x2749, 0x1078, 0x23ca, 0x1078, 0x38c6, 0x0f7e, 0x2079, 0x5000, + 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x276f, 0x706c, 0xa086, + 0x0001, 0x00c0, 0x275e, 0x706e, 0x0078, 0x2802, 0x706c, 0xa086, + 0x0005, 0x00c0, 0x276d, 0x7088, 0x2068, 0x681b, 0x0004, 0x6817, + 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f, 0x0000, 0x2011, + 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x2790, 0xa186, 0x0007, + 0x00c0, 0x2780, 0x2009, 0x5038, 0x200b, 0x0005, 0x0078, 0x2790, + 0x2009, 0x5013, 0x2104, 0x2009, 0x5012, 0x200a, 0x2009, 0x5038, + 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001, 0x0078, 0x2792, + 0x706f, 0x0000, 0x1078, 0x4633, 0x157e, 0x20a9, 0x0010, 0x2039, + 0x0000, 0x1078, 0x36b0, 0xa7b8, 0x0100, 0x0070, 0x27a1, 0x0078, + 0x2799, 0x157f, 0x7000, 0x0079, 0x27a5, 0x27d3, 0x27ba, 0x27ba, + 0x27ad, 0x27d3, 0x27d3, 0x27d3, 0x27d3, 0x2021, 0x505a, 0x2404, + 0xa005, 0x0040, 0x27d3, 0xad06, 0x00c0, 0x27ba, 0x6800, 0x2022, + 0x0078, 0x27ca, 0x6820, 0xa084, 0x0001, 0x00c0, 0x27c6, 0x6f14, + 0x1078, 0x37bd, 0x1078, 0x33ae, 0x0078, 0x27ca, 0x7060, 0x2060, + 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, + 0x6822, 0x1078, 0x1c53, 0x2021, 0x7400, 0x1078, 0x280f, 0x2021, + 0x505a, 0x1078, 0x280f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7300, + 0x1078, 0x280f, 0x8420, 0x0070, 0x27e7, 0x0078, 0x27e0, 0x2061, + 0x5300, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018, 0x6110, 0x81ff, + 0x0040, 0x27f6, 0xa102, 0x0050, 0x27f6, 0x6012, 0x601b, 0x0000, + 0xace0, 0x0010, 0x0070, 0x27fe, 0x0078, 0x27ed, 0x8421, 0x00c0, + 0x27eb, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040, 0x2809, 0x1078, + 0x39cc, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078, 0x2438, 0x047e, + 0x2404, 0xa005, 0x0040, 0x2823, 0x2068, 0x6800, 0x007e, 0x6a1a, + 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078, 0x1c53, + 0x007f, 0x0078, 0x2811, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, + 0x0003, 0x0050, 0x282d, 0x1078, 0x23ca, 0x2300, 0x0079, 0x2830, + 0x2833, 0x28a6, 0x28c3, 0xa282, 0x0002, 0x0040, 0x2839, 0x1078, + 0x23ca, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x2840, + 0x2848, 0x2848, 0x284a, 0x287e, 0x33e3, 0x2848, 0x287e, 0x2848, + 0x1078, 0x23ca, 0x7780, 0x1078, 0x36b0, 0x7780, 0xa7bc, 0x0f00, + 0x1078, 0x37bd, 0x6018, 0xa005, 0x0040, 0x2875, 0x2021, 0x7400, + 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x28de, 0x0040, 0x2875, + 0x157e, 0x20a9, 0x0000, 0x2021, 0x7300, 0x047e, 0x2009, 0x0004, + 0x2011, 0x0010, 0x1078, 0x28de, 0x047f, 0x0040, 0x2874, 0x8420, + 0x0070, 0x2874, 0x0078, 0x2865, 0x157f, 0x8738, 0xa784, 0x001f, + 0x00c0, 0x2850, 0x0078, 0x2461, 0x0078, 0x2461, 0x7780, 0x1078, + 0x37bd, 0x6018, 0xa005, 0x0040, 0x28a4, 0x2021, 0x7400, 0x2009, + 0x0005, 0x2011, 0x0020, 0x1078, 0x28de, 0x0040, 0x28a4, 0x157e, + 0x20a9, 0x0000, 0x2021, 0x7300, 0x047e, 0x2009, 0x0005, 0x2011, + 0x0020, 0x1078, 0x28de, 0x047f, 0x0040, 0x28a3, 0x8420, 0x0070, + 0x28a3, 0x0078, 0x2894, 0x157f, 0x0078, 0x2461, 0x2200, 0x0079, + 0x28a9, 0x28ac, 0x28ae, 0x28ae, 0x1078, 0x23ca, 0x2009, 0x0012, + 0x706c, 0xa086, 0x0002, 0x0040, 0x28b7, 0x2009, 0x000e, 0x6818, + 0xa084, 0x8000, 0x0040, 0x28bd, 0x691a, 0x706f, 0x0000, 0x7073, + 0x0001, 0x0078, 0x3854, 0x2200, 0x0079, 0x28c6, 0x28cb, 0x28ae, + 0x28c9, 0x1078, 0x23ca, 0x1078, 0x4633, 0x7000, 0xa086, 0x0001, + 0x00c0, 0x3373, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, + 0x1078, 0x3366, 0x0040, 0x3373, 0x0078, 0x2573, 0x2404, 0xa005, + 0x0040, 0x2901, 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, + 0x28ed, 0x2d20, 0x007f, 0x0078, 0x28df, 0x007f, 0x2022, 0x691a, + 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078, 0x1c53, 0x6010, + 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x33c4, + 0x007c, 0xa085, 0x0001, 0x0078, 0x2900, 0x2300, 0x0079, 0x2908, + 0x290d, 0x290b, 0x29a6, 0x1078, 0x23ca, 0x78ec, 0xa084, 0x0001, + 0x00c0, 0x2921, 0x7000, 0xa086, 0x0004, 0x00c0, 0x2919, 0x0078, + 0x2944, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, + 0x3373, 0x78e4, 0xa005, 0x00d0, 0x2944, 0x0018, 0x2438, 0x2008, + 0xa084, 0x0030, 0x00c0, 0x2930, 0x781b, 0x004f, 0x0078, 0x2438, + 0x78ec, 0xa084, 0x0003, 0x0040, 0x292c, 0x2100, 0xa084, 0x0007, + 0x0079, 0x293a, 0x297d, 0x2988, 0x296e, 0x2942, 0x38b9, 0x38b9, + 0x2942, 0x2997, 0x1078, 0x23ca, 0x7000, 0xa086, 0x0004, 0x00c0, + 0x295e, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2954, 0x2011, 0x0002, + 0x2019, 0x0000, 0x0078, 0x2827, 0x706c, 0xa086, 0x0006, 0x0040, + 0x294e, 0x706c, 0xa086, 0x0004, 0x0040, 0x294e, 0x79e4, 0xa184, + 0x0030, 0x0040, 0x2968, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x296a, + 0x0078, 0x2f43, 0x2001, 0x0003, 0x0078, 0x2cd7, 0x6818, 0xa084, + 0x8000, 0x0040, 0x2975, 0x681b, 0x001d, 0x1078, 0x368f, 0x782b, + 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x6818, 0xa084, 0x8000, + 0x0040, 0x2984, 0x681b, 0x001d, 0x1078, 0x368f, 0x0078, 0x3884, + 0x6818, 0xa084, 0x8000, 0x0040, 0x298f, 0x681b, 0x001d, 0x1078, + 0x368f, 0x782b, 0x3008, 0x781b, 0x00d2, 0x0078, 0x2438, 0x6818, + 0xa084, 0x8000, 0x0040, 0x299e, 0x681b, 0x001d, 0x1078, 0x368f, + 0x782b, 0x3008, 0x781b, 0x0093, 0x0078, 0x2438, 0xa584, 0x000f, + 0x00c0, 0x29c3, 0x7000, 0x0079, 0x29ad, 0x2461, 0x29b7, 0x29b5, + 0x3373, 0x3373, 0x3373, 0x3373, 0x29b5, 0x1078, 0x23ca, 0x1078, + 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x3366, 0x0040, + 0x3373, 0x0078, 0x2573, 0x78e4, 0xa005, 0x00d0, 0x2944, 0x0018, + 0x2944, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29d2, 0x781b, 0x004f, + 0x0078, 0x2438, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ce, 0x2100, + 0xa184, 0x0007, 0x0079, 0x29dc, 0x29ee, 0x29f2, 0x29e6, 0x29e4, + 0x38b9, 0x38b9, 0x29e4, 0x38af, 0x1078, 0x23ca, 0x1078, 0x3697, + 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x1078, 0x3697, + 0x0078, 0x3884, 0x1078, 0x3697, 0x782b, 0x3008, 0x781b, 0x00d2, + 0x0078, 0x2438, 0x1078, 0x3697, 0x782b, 0x3008, 0x781b, 0x0093, + 0x0078, 0x2438, 0x2300, 0x0079, 0x2a05, 0x2a0a, 0x2a08, 0x2a0c, + 0x1078, 0x23ca, 0x0078, 0x3081, 0x681b, 0x0008, 0x78a3, 0x0000, + 0x79e4, 0xa184, 0x0030, 0x0040, 0x3081, 0x78ec, 0xa084, 0x0003, + 0x0040, 0x3081, 0xa184, 0x0007, 0x0079, 0x2a1e, 0x2a26, 0x29f2, + 0x296e, 0x3854, 0x38b9, 0x38b9, 0x2a26, 0x38af, 0x1078, 0x3868, + 0x0078, 0x2438, 0xa282, 0x0005, 0x0050, 0x2a30, 0x1078, 0x23ca, + 0x2300, 0x0079, 0x2a33, 0x2a36, 0x2c84, 0x2c92, 0x2200, 0x0079, + 0x2a39, 0x2a53, 0x2a40, 0x2a53, 0x2a3e, 0x2c69, 0x1078, 0x23ca, + 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, + 0x366b, 0xa08a, 0x0004, 0x00c8, 0x366b, 0x0079, 0x2a4f, 0x366b, + 0x366b, 0x366b, 0x3619, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, + 0x0040, 0x2a64, 0x0078, 0x366b, 0x7000, 0xa005, 0x00c0, 0x2a5a, + 0x2011, 0x0004, 0x0078, 0x31f5, 0xa184, 0x00ff, 0xa08a, 0x0010, + 0x00c8, 0x366b, 0x0079, 0x2a6c, 0x2a7e, 0x2a7c, 0x2a96, 0x2a9a, + 0x2b55, 0x366b, 0x366b, 0x2b57, 0x366b, 0x366b, 0x2c65, 0x2c65, + 0x366b, 0x366b, 0x366b, 0x2c67, 0x1078, 0x23ca, 0xa684, 0x1000, + 0x0040, 0x2a8b, 0x2001, 0x0500, 0x8000, 0x8000, 0x783a, 0x781b, + 0x0091, 0x0078, 0x2438, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a94, + 0x681b, 0x001d, 0x0078, 0x2a82, 0x0078, 0x3854, 0x681b, 0x001d, + 0x0078, 0x367b, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x2adb, + 0x6820, 0xa084, 0x0001, 0x00c0, 0x2ae1, 0x6818, 0xa086, 0x0008, + 0x00c0, 0x2aac, 0x681b, 0x0000, 0xa684, 0x0400, 0x0040, 0x2b51, + 0xa684, 0x0080, 0x0040, 0x2ad7, 0x7097, 0x0000, 0x6818, 0xa084, + 0x003f, 0xa08a, 0x000d, 0x0050, 0x2ad7, 0xa08a, 0x000c, 0x7196, + 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061, 0x78aa, 0x157e, + 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, + 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x781b, + 0x0058, 0x0078, 0x2438, 0xa684, 0x1000, 0x0040, 0x2ae1, 0x0078, + 0x2438, 0xa684, 0x0060, 0x0040, 0x2b4d, 0xa684, 0x0800, 0x0040, + 0x2b4d, 0xa684, 0x8000, 0x00c0, 0x2aef, 0x0078, 0x2b09, 0xa6b4, + 0x7fff, 0x7e5a, 0x6eb6, 0x789b, 0x0076, 0x7aac, 0x79ac, 0x78ac, + 0x801b, 0x00c8, 0x2afc, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, + 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, + 0x68ae, 0xa684, 0x4000, 0x0040, 0x2b11, 0xa6b4, 0xbfff, 0x7e5a, + 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0, 0x2b1e, 0x1078, 0x46e9, + 0x1078, 0x48e6, 0x781b, 0x0064, 0x0078, 0x2438, 0xa006, 0x1078, + 0x49ed, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, + 0x2b2d, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, + 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x2b3f, 0xa6b5, + 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064, 0x0078, 0x2438, 0x781b, + 0x0064, 0x2200, 0xa115, 0x00c0, 0x2b49, 0x1078, 0x48f7, 0x0078, + 0x2438, 0x1078, 0x4942, 0x0078, 0x2438, 0x781b, 0x0065, 0x0078, + 0x2438, 0x781b, 0x0058, 0x0078, 0x2438, 0x1078, 0x23ca, 0x0078, + 0x2bb8, 0x6920, 0xa184, 0x0100, 0x0040, 0x2b6f, 0xa18c, 0xfeff, + 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002, + 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x2ba7, 0xa184, + 0x0200, 0x0040, 0x2ba7, 0xa18c, 0xfdff, 0x6922, 0x0c7e, 0x7054, + 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef, + 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2ba7, + 0x1078, 0x37b9, 0x1078, 0x34c7, 0x88ff, 0x0040, 0x2ba7, 0x789b, + 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, + 0x0400, 0x00c0, 0x2ba1, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, + 0x2438, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7e58, + 0xa684, 0x0400, 0x00c0, 0x2bb0, 0x781b, 0x0058, 0x0078, 0x2438, + 0x781b, 0x0065, 0x0078, 0x2438, 0x0078, 0x3673, 0x0078, 0x3673, + 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x2bb6, 0x789b, + 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0, 0x2bf6, + 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x2bee, 0x0048, + 0x2bd3, 0x0078, 0x2bf0, 0xa380, 0x0002, 0xa102, 0x00c8, 0x2bee, + 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, + 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5, 0x6006, 0x0c7f, + 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2ba8, 0x0078, 0x2b59, + 0x24a8, 0x7aa8, 0x00f0, 0x2bf0, 0x0078, 0x2bc1, 0xa284, 0x00f0, + 0xa086, 0x0020, 0x00c0, 0x2c56, 0x8318, 0x8318, 0x2300, 0xa102, + 0x0040, 0x2c06, 0x0048, 0x2c06, 0x0078, 0x2c53, 0xa286, 0x0023, + 0x0040, 0x2bb6, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, + 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, + 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, + 0xa184, 0x0010, 0x0040, 0x2c2a, 0x1078, 0x37b9, 0x1078, 0x35d6, + 0x0078, 0x2c39, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48, + 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2ba7, 0x1078, 0x37b9, 0x1078, + 0x34c7, 0x88ff, 0x0040, 0x2ba7, 0x789b, 0x0060, 0x2800, 0x78aa, + 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2c4d, 0x782b, + 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, + 0x0065, 0x0078, 0x2438, 0x7aa8, 0x0078, 0x2bc1, 0x8318, 0x2300, + 0xa102, 0x0040, 0x2c5f, 0x0048, 0x2c5f, 0x0078, 0x2bc1, 0xa284, + 0x0080, 0x00c0, 0x367b, 0x0078, 0x3673, 0x0078, 0x367b, 0x0078, + 0x366b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, + 0x0040, 0x2c74, 0x1078, 0x23ca, 0x7aa8, 0xa294, 0x00ff, 0x78a8, + 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x366b, 0x0079, 0x2c80, + 0x366b, 0x3414, 0x366b, 0x356b, 0xa282, 0x0000, 0x00c0, 0x2c8a, + 0x1078, 0x23ca, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b, 0x0065, + 0x0078, 0x2438, 0xa282, 0x0003, 0x00c0, 0x2c98, 0x1078, 0x23ca, + 0xa484, 0x8000, 0x00c0, 0x2cbb, 0x706c, 0xa005, 0x0040, 0x2ca2, + 0x1078, 0x23ca, 0x6f14, 0x7782, 0xa7bc, 0x0f00, 0x1078, 0x37bd, + 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x00c0, + 0x2ca6, 0x1078, 0x3693, 0x706f, 0x0002, 0x2009, 0x5038, 0x200b, + 0x0009, 0x0078, 0x2cbd, 0x1078, 0x369f, 0x782b, 0x3008, 0x781b, + 0x0065, 0x0078, 0x2438, 0xa282, 0x0004, 0x0050, 0x2cc9, 0x1078, + 0x23ca, 0x2300, 0x0079, 0x2ccc, 0x2ccf, 0x2db8, 0x2deb, 0xa286, + 0x0003, 0x0040, 0x2cd5, 0x1078, 0x23ca, 0x2001, 0x0000, 0x007e, + 0x68c0, 0xa005, 0x0040, 0x2cde, 0x7003, 0x0003, 0x68a0, 0xa084, + 0x2000, 0x0040, 0x2ce7, 0x6008, 0xa085, 0x0002, 0x600a, 0x007f, + 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2cee, 0x2461, 0x2cf8, + 0x2cf8, 0x2eed, 0x2f29, 0x2461, 0x2f29, 0x2cf6, 0x1078, 0x23ca, + 0xa684, 0x1000, 0x00c0, 0x2d00, 0x1078, 0x4633, 0x0040, 0x2d92, + 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2d48, 0xa186, 0x0008, 0x00c0, + 0x2d17, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, + 0x3366, 0x0040, 0x2d48, 0x1078, 0x4633, 0x0078, 0x2d2f, 0xa186, + 0x0028, 0x00c0, 0x2d48, 0x1078, 0x4633, 0x6008, 0xa084, 0xffef, + 0x600a, 0x6018, 0xa005, 0x0040, 0x2d2f, 0x8001, 0x601a, 0xa005, + 0x0040, 0x2d2f, 0x8001, 0xa005, 0x0040, 0x2d2f, 0x601e, 0x6820, + 0xa084, 0x0001, 0x0040, 0x2461, 0x6820, 0xa084, 0xfffe, 0x6822, + 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, + 0xa005, 0x2d00, 0x00c0, 0x2d45, 0x6002, 0x6006, 0x0078, 0x2461, + 0x017e, 0x1078, 0x2e1c, 0x017f, 0xa684, 0xdf00, 0x681e, 0x682b, + 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2d92, 0xa186, 0x0002, 0x00c0, + 0x2d92, 0xa684, 0x0800, 0x00c0, 0x2d65, 0xa684, 0x0060, 0x0040, + 0x2d65, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820, 0xa084, 0x0800, + 0x00c0, 0x2d92, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, + 0xa290, 0x5280, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, + 0x2d7b, 0x0078, 0x2d81, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, + 0x8211, 0xa384, 0x0400, 0x0040, 0x2d8e, 0x68a0, 0xa084, 0x0100, + 0x00c0, 0x2d8e, 0x1078, 0x2ea0, 0x0078, 0x2461, 0x6008, 0xa085, + 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040, 0x2d9a, + 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x33b5, 0x1078, + 0x33c4, 0x00c0, 0x2da7, 0x6008, 0xa084, 0xffef, 0x600a, 0x6820, + 0xa084, 0x0001, 0x00c0, 0x2db0, 0x1078, 0x33ae, 0x0078, 0x2db4, + 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1c53, 0x0078, 0x2461, + 0xa282, 0x0004, 0x0048, 0x2dbe, 0x1078, 0x23ca, 0x2200, 0x0079, + 0x2dc1, 0x2dbc, 0x2dc5, 0x2dd2, 0x2dc5, 0x7000, 0xa086, 0x0005, + 0x0040, 0x2dce, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b, 0x0065, + 0x0078, 0x2438, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, + 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0040, + 0x2de7, 0xa186, 0x0000, 0x0040, 0x2de7, 0x0078, 0x366b, 0x781b, + 0x0065, 0x0078, 0x2438, 0x6820, 0xa085, 0x0004, 0x6822, 0x82ff, + 0x00c0, 0x2df6, 0x1078, 0x368f, 0x0078, 0x2dfd, 0x8211, 0x0040, + 0x2dfb, 0x1078, 0x23ca, 0x1078, 0x369f, 0x782b, 0x3008, 0x781b, + 0x0065, 0x0078, 0x2438, 0x702c, 0x8003, 0x0048, 0x2e0d, 0x2019, + 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x1078, 0x38de, 0x7830, + 0xa084, 0x00c0, 0x00c0, 0x2e19, 0x0018, 0x2e19, 0x791a, 0xa006, + 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0, 0x2e26, + 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e9f, 0xa684, 0x0800, + 0x00c0, 0x2e48, 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684, 0x0800, + 0x00c0, 0x2e48, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x703c, 0xa005, + 0x00c0, 0x2e40, 0x2200, 0xa105, 0x0040, 0x2e47, 0x703f, 0x0015, + 0x7000, 0xa086, 0x0006, 0x0040, 0x2e47, 0x1078, 0x4633, 0x007c, + 0xa684, 0x0020, 0x0040, 0x2e6a, 0xa684, 0x4000, 0x0040, 0x2e56, + 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e40, 0x68b4, 0xa084, + 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e50, 0x703c, 0xa005, + 0x00c0, 0x2e64, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x692e, 0x6a32, + 0x0078, 0x2e40, 0xa684, 0x4000, 0x0040, 0x2e74, 0x682f, 0x0000, + 0x6833, 0x0000, 0x0078, 0x2e40, 0x68b4, 0xa084, 0x4800, 0xa635, + 0xa684, 0x4000, 0x00c0, 0x2e6e, 0x703c, 0xa005, 0x00c0, 0x2e82, + 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8, 0x2e89, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32, - 0x2100, 0xa205, 0x00c0, 0x2826, 0x0078, 0x27e0, 0x7000, 0xa086, - 0x0006, 0x0040, 0x282f, 0x1078, 0x362f, 0x0078, 0x27e0, 0x007c, - 0xa384, 0x0200, 0x0040, 0x2838, 0x6008, 0xa085, 0x0002, 0x600a, - 0x681b, 0x0006, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, + 0x2100, 0xa205, 0x00c0, 0x2e96, 0x0078, 0x2e40, 0x7000, 0xa086, + 0x0006, 0x0040, 0x2e9f, 0x1078, 0x49ed, 0x0078, 0x2e40, 0x007c, + 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200, 0x0040, 0x2eac, + 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006, 0x688f, 0x0000, + 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, - 0x7000, 0x0079, 0x284b, 0x2853, 0x2855, 0x285e, 0x2853, 0x2853, - 0x2853, 0x2853, 0x2853, 0x1078, 0x1eac, 0x6820, 0xa084, 0x0001, - 0x00c0, 0x285e, 0x1078, 0x2cc9, 0x0078, 0x2864, 0x7054, 0x2c50, - 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3957, 0x2404, 0xa005, - 0x0040, 0x286d, 0x2020, 0x0078, 0x2866, 0x2d22, 0x206b, 0x0000, - 0x007c, 0x1078, 0x2cd0, 0x1078, 0x2cdf, 0x682b, 0x0000, 0x789b, - 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x366b, 0xa684, 0x0800, - 0x0040, 0x2886, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818, 0xa084, - 0x8000, 0x0040, 0x2896, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2894, - 0x681b, 0x001e, 0x0078, 0x2896, 0x681b, 0x0000, 0x2021, 0x3957, - 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1a26, - 0x0078, 0x1f03, 0x1078, 0x27ce, 0x682b, 0x0000, 0x789b, 0x000e, - 0x6f14, 0x1078, 0x316f, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084, - 0x8000, 0x0040, 0x28b5, 0x7038, 0x681a, 0xa68c, 0xdf00, 0x691e, - 0x70a3, 0x0000, 0x0078, 0x1f03, 0xa006, 0x1078, 0x32f5, 0x6817, - 0x0000, 0x681b, 0x0001, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, - 0x7000, 0x0079, 0x28cb, 0x28d3, 0x28d5, 0x28d5, 0x28d7, 0x28d7, - 0x28d7, 0x28d7, 0x28d3, 0x1078, 0x1eac, 0x1078, 0x2cdf, 0x6008, - 0xa084, 0xffef, 0x600a, 0x0078, 0x2caa, 0x2300, 0x0079, 0x28e0, - 0x28e3, 0x28e5, 0x2939, 0x1078, 0x1eac, 0x7000, 0x0079, 0x28e8, - 0x28f0, 0x28f2, 0x28f2, 0x290d, 0x28f2, 0x291a, 0x290d, 0x28f0, - 0x1078, 0x1eac, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x2909, - 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c, - 0xa084, 0xffdf, 0x681e, 0x1078, 0x32f5, 0x1078, 0x3571, 0x0078, - 0x311c, 0xa684, 0x2000, 0x0040, 0x28fc, 0x6818, 0xa084, 0x8000, - 0x0040, 0x291a, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x291a, - 0x681b, 0x0007, 0x2009, 0x391e, 0x210c, 0xa186, 0x0000, 0x0040, - 0x292f, 0xa186, 0x0001, 0x0040, 0x2933, 0x2009, 0x3935, 0x200b, - 0x000b, 0x70a3, 0x0001, 0x781b, 0x0047, 0x0078, 0x1efb, 0x781b, - 0x00df, 0x0078, 0x1efb, 0x2009, 0x3935, 0x200b, 0x000a, 0x0078, - 0x1efb, 0x1078, 0x1eac, 0x2300, 0x0079, 0x293e, 0x2941, 0x2943, - 0x2976, 0x1078, 0x1eac, 0x7000, 0x0079, 0x2946, 0x294e, 0x2950, - 0x2950, 0x296b, 0x2950, 0x2972, 0x296b, 0x294e, 0x1078, 0x1eac, - 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x2967, 0xa6b4, 0xffbf, - 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf, - 0x681e, 0x1078, 0x32f5, 0x1078, 0x3571, 0x0078, 0x311c, 0xa684, - 0x2000, 0x0040, 0x295a, 0x6818, 0xa084, 0x8000, 0x0040, 0x2972, - 0x681b, 0x0007, 0x781b, 0x00e6, 0x0078, 0x1efb, 0x6820, 0xa085, - 0x0004, 0x6822, 0x1078, 0x30e7, 0xa6b5, 0x0800, 0x1078, 0x2f7d, - 0x781b, 0x0067, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2987, 0x298a, - 0x298c, 0x298e, 0x1078, 0x1eac, 0x1078, 0x1eac, 0xa684, 0x0400, - 0x00c0, 0x29ae, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfdff, 0xa18c, - 0xfeff, 0x6922, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, - 0x785a, 0x79e4, 0xa184, 0x0020, 0x00c0, 0x29aa, 0x2001, 0x0014, - 0x0078, 0x26ad, 0xa184, 0x0007, 0x0079, 0x29e6, 0x7a90, 0xa294, - 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x29e4, 0x789b, - 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x29d5, 0x7ba8, 0x7ba8, - 0xa386, 0x0001, 0x00c0, 0x29c8, 0x2009, 0xfff7, 0x0078, 0x29ce, - 0xa386, 0x0003, 0x00c0, 0x29d5, 0x2009, 0xffef, 0x0c7e, 0x7048, - 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, - 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, - 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x311c, 0x239b, 0x23a8, - 0x3124, 0x3124, 0x29ee, 0x29ee, 0x29ee, 0x3124, 0x1078, 0x1eac, - 0x79e4, 0xa184, 0x0030, 0x00c0, 0x2a06, 0x70a0, 0xa086, 0x0002, - 0x00c0, 0x29fe, 0x2011, 0x0002, 0x0078, 0x2288, 0x6818, 0xa085, - 0x8000, 0x681a, 0x2001, 0x0014, 0x0078, 0x26ad, 0xa184, 0x0007, - 0x0079, 0x2a0a, 0x311c, 0x311c, 0x2a12, 0x311c, 0x3144, 0x3144, - 0x311c, 0x311c, 0xa684, 0x0080, 0x0040, 0x2a41, 0x71c8, 0x81ff, - 0x0040, 0x2a41, 0xa182, 0x000d, 0x00d0, 0x2a22, 0x70cb, 0x0000, - 0x0078, 0x2a27, 0xa182, 0x000c, 0x70ca, 0x2009, 0x000c, 0x789b, - 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e, 0x70cc, 0x8114, 0xa210, - 0x72ce, 0xa080, 0x000b, 0xad00, 0x2098, 0x20a1, 0x012b, 0x789b, - 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, - 0x3124, 0xa684, 0x0400, 0x00c0, 0x2a82, 0x6820, 0xa084, 0x0001, - 0x0040, 0x3124, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x2a56, - 0xa086, 0x0060, 0x00c0, 0x2a56, 0xa18d, 0x4000, 0xa18c, 0xfffb, - 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, - 0x6818, 0xa085, 0x8000, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, - 0x2d07, 0xa18c, 0x00f8, 0x00c0, 0x2d07, 0x157e, 0x137e, 0x147e, - 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, - 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882, - 0x0078, 0x3124, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a89, 0x681b, - 0x0008, 0x781b, 0x00da, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2a90, - 0x2a95, 0x2b18, 0x2a93, 0x1078, 0x1eac, 0x7000, 0xa084, 0x0007, - 0x0079, 0x2a9a, 0x2aa2, 0x2aa4, 0x2ac0, 0x2aa2, 0x2aa2, 0x1f03, - 0x2aa2, 0x2aa2, 0x1078, 0x1eac, 0x6920, 0xa18d, 0x0001, 0x6922, - 0x6800, 0x6006, 0xa005, 0x00c0, 0x2aae, 0x6002, 0x681c, 0xa084, - 0x000e, 0x0040, 0x2aba, 0x7014, 0x68ba, 0x712c, 0xa188, 0x4280, - 0x0078, 0x2abc, 0x2009, 0x4380, 0x2104, 0x6802, 0x2d0a, 0x7156, - 0x6920, 0xa184, 0x8000, 0x00c0, 0x2acc, 0x68af, 0x0000, 0x68b3, - 0x0000, 0xa18d, 0x8000, 0x6922, 0x6eb6, 0xa684, 0x0060, 0x0040, - 0x2b16, 0xa684, 0x0800, 0x00c0, 0x2add, 0x6894, 0x68a6, 0x6898, - 0x68aa, 0x1078, 0x32f5, 0x0078, 0x2b16, 0xa684, 0x0020, 0x0040, - 0x2aea, 0xa006, 0x1078, 0x362f, 0x79d8, 0x7adc, 0x69aa, 0x6aa6, - 0x0078, 0x2af0, 0x1078, 0x30a6, 0x69aa, 0x6aa6, 0x1078, 0x362f, - 0xa684, 0x8000, 0x0040, 0x2b16, 0xa684, 0x7fff, 0x68b6, 0x789b, - 0x0074, 0x1078, 0x316f, 0x2010, 0x1078, 0x316f, 0x2008, 0xa684, - 0x0020, 0x00c0, 0x2b0e, 0x1078, 0x316f, 0x801b, 0x00c8, 0x2b09, + 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079, 0x2ec7, 0x2461, + 0x2ed1, 0x2eda, 0x2ecf, 0x2ecf, 0x2ecf, 0x2ecf, 0x2ecf, 0x1078, + 0x23ca, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2eda, 0x1078, 0x33ae, + 0x0078, 0x2ee0, 0x7060, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, + 0x2021, 0x505a, 0x2404, 0xa005, 0x0040, 0x2ee9, 0x2020, 0x0078, + 0x2ee2, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x33b5, 0x1078, + 0x33c4, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b, 0x0000, 0x789b, + 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4a35, 0xa684, 0x0800, + 0x0040, 0x2f06, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818, 0xa084, + 0x8000, 0x0040, 0x2f16, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2f14, + 0x681b, 0x001e, 0x0078, 0x2f16, 0x681b, 0x0000, 0x2021, 0x505a, + 0x2404, 0xad06, 0x0040, 0x2f1d, 0x7460, 0x6800, 0x2022, 0x68c3, + 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1c53, 0x0078, + 0x2461, 0x1078, 0x2e1c, 0x682b, 0x0000, 0x2001, 0x000e, 0x6f14, + 0x1078, 0x38e4, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084, 0x8000, + 0x0040, 0x2f3c, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x706f, + 0x0000, 0x0078, 0x2461, 0x7000, 0xa005, 0x00c0, 0x2f49, 0x0078, + 0x2461, 0xa006, 0x1078, 0x4633, 0x6817, 0x0000, 0x681b, 0x0014, + 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa085, 0x00ff, + 0x6822, 0x7000, 0x0079, 0x2f5c, 0x2461, 0x2f66, 0x2f66, 0x2f68, + 0x2f68, 0x2f68, 0x2f68, 0x2f64, 0x1078, 0x23ca, 0x1078, 0x33c4, + 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x337e, 0x2300, 0x0079, + 0x2f71, 0x2f74, 0x2f76, 0x2faf, 0x1078, 0x23ca, 0x7000, 0x0079, + 0x2f79, 0x2461, 0x2f83, 0x2f83, 0x2f9e, 0x2f83, 0x2fab, 0x2f9e, + 0x2f81, 0x1078, 0x23ca, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, + 0x2f9a, 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, + 0x681c, 0xa084, 0xffdf, 0x681e, 0x1078, 0x4633, 0x1078, 0x48f7, + 0x0078, 0x3854, 0xa684, 0x2000, 0x0040, 0x2f8d, 0x6818, 0xa084, + 0x8000, 0x0040, 0x2fab, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, + 0x2fab, 0x681b, 0x0007, 0x1078, 0x3868, 0x0078, 0x2438, 0x1078, + 0x23ca, 0x2300, 0x0079, 0x2fb4, 0x2fb7, 0x2fb9, 0x2fec, 0x1078, + 0x23ca, 0x7000, 0x0079, 0x2fbc, 0x2461, 0x2fc6, 0x2fc6, 0x2fe1, + 0x2fc6, 0x2fe8, 0x2fe1, 0x2fc4, 0x1078, 0x23ca, 0xa684, 0x0060, + 0xa086, 0x0060, 0x00c0, 0x2fdd, 0xa6b4, 0xffbf, 0xa6b4, 0xbfff, + 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf, 0x681e, 0x1078, + 0x4633, 0x1078, 0x48f7, 0x0078, 0x3854, 0xa684, 0x2000, 0x0040, + 0x2fd0, 0x6818, 0xa084, 0x8000, 0x0040, 0x2fe8, 0x681b, 0x0007, + 0x781b, 0x00d2, 0x0078, 0x2438, 0x6820, 0xa085, 0x0004, 0x6822, + 0x1078, 0x381f, 0xa6b5, 0x0800, 0x1078, 0x368f, 0x782b, 0x3008, + 0x781b, 0x0065, 0x0078, 0x2438, 0x2300, 0x0079, 0x2fff, 0x3002, + 0x3004, 0x3006, 0x1078, 0x23ca, 0x0078, 0x367b, 0xa684, 0x0400, + 0x00c0, 0x302f, 0x79e4, 0xa184, 0x0020, 0x0040, 0x3016, 0x78ec, + 0xa084, 0x0003, 0x0040, 0x3016, 0x782b, 0x3009, 0x789b, 0x0060, + 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, + 0x0040, 0x3027, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x302b, 0x2001, + 0x0014, 0x0078, 0x2cd7, 0xa184, 0x0007, 0x0079, 0x3067, 0x7a90, + 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3065, + 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x3056, 0x7ba8, + 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x3049, 0x2009, 0xfff7, 0x0078, + 0x304f, 0xa386, 0x0003, 0x00c0, 0x3056, 0x2009, 0xffef, 0x0c7e, + 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, + 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, + 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3854, 0x297d, + 0x2988, 0x3071, 0x3079, 0x306f, 0x306f, 0x3854, 0x3854, 0x1078, + 0x23ca, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, + 0x385e, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, + 0x3854, 0x79e4, 0xa184, 0x0030, 0x0040, 0x308b, 0x78ec, 0xa084, + 0x0003, 0x00c0, 0x30b2, 0x7000, 0xa086, 0x0004, 0x00c0, 0x30a5, + 0x706c, 0xa086, 0x0002, 0x00c0, 0x309b, 0x2011, 0x0002, 0x2019, + 0x0000, 0x0078, 0x2827, 0x706c, 0xa086, 0x0006, 0x0040, 0x3095, + 0x706c, 0xa086, 0x0004, 0x0040, 0x3095, 0x7000, 0xa086, 0x0000, + 0x0040, 0x2438, 0x6818, 0xa085, 0x8000, 0x681a, 0x2001, 0x0014, + 0x0078, 0x2cd7, 0xa184, 0x0007, 0x0079, 0x30b6, 0x3854, 0x3854, + 0x30be, 0x3854, 0x38b9, 0x38b9, 0x3854, 0x3854, 0xa684, 0x0080, + 0x0040, 0x30ed, 0x7194, 0x81ff, 0x0040, 0x30ed, 0xa182, 0x000d, + 0x00d0, 0x30ce, 0x7097, 0x0000, 0x0078, 0x30d3, 0xa182, 0x000c, + 0x7096, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, + 0x147e, 0x7098, 0x8114, 0xa210, 0x729a, 0xa080, 0x000b, 0xad00, + 0x2098, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, + 0x147f, 0x137f, 0x157f, 0x0078, 0x385e, 0xa684, 0x0400, 0x00c0, + 0x312e, 0x6820, 0xa084, 0x0001, 0x0040, 0x385e, 0xa68c, 0x0060, + 0xa684, 0x0060, 0x0040, 0x3102, 0xa086, 0x0060, 0x00c0, 0x3102, + 0xa18d, 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6, 0x789b, 0x0060, + 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xa085, 0x8000, 0x681a, + 0x78aa, 0x8008, 0x810c, 0x0040, 0x33dd, 0xa18c, 0x00f8, 0x00c0, + 0x33dd, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, + 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, + 0x157f, 0x6814, 0x8007, 0x7882, 0x0078, 0x385e, 0x6818, 0xa084, + 0x8000, 0x0040, 0x3135, 0x681b, 0x0008, 0x781b, 0x00c8, 0x0078, + 0x2438, 0x2300, 0x0079, 0x313c, 0x3141, 0x31e0, 0x313f, 0x1078, + 0x23ca, 0x7000, 0xa084, 0x0007, 0x0079, 0x3146, 0x2461, 0x3150, + 0x3185, 0x315b, 0x314e, 0x2461, 0x314e, 0x314e, 0x1078, 0x23ca, + 0x681c, 0xa084, 0x2000, 0x0040, 0x3169, 0x6008, 0xa085, 0x0002, + 0x600a, 0x0078, 0x3169, 0x68c0, 0xa005, 0x00c0, 0x3185, 0x6920, + 0xa18d, 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800, 0x706a, 0x0078, + 0x317f, 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800, 0x6006, 0xa005, + 0x00c0, 0x3173, 0x6002, 0x681c, 0xa084, 0x000e, 0x0040, 0x317f, + 0x7014, 0x68ba, 0x7130, 0xa188, 0x7300, 0x0078, 0x3181, 0x2009, + 0x7400, 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6, 0xa684, 0x0060, + 0x0040, 0x31de, 0xa684, 0x0800, 0x00c0, 0x3199, 0xa684, 0x7fff, + 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4633, 0x0078, + 0x31de, 0xa684, 0x0020, 0x0040, 0x31ae, 0x68c0, 0xa005, 0x0040, + 0x31a5, 0x1078, 0x4a35, 0x0078, 0x31a8, 0xa006, 0x1078, 0x49ed, + 0x79d8, 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x31b4, 0x1078, 0x37ca, + 0x69aa, 0x6aa6, 0x1078, 0x49ed, 0xa684, 0x8000, 0x0040, 0x31de, + 0xa684, 0x7fff, 0x68b6, 0x2001, 0x0076, 0x1078, 0x38e4, 0x2010, + 0x2001, 0x0078, 0x1078, 0x38e4, 0x2008, 0xa684, 0x0020, 0x00c0, + 0x31d6, 0x2001, 0x007a, 0x1078, 0x38e4, 0x801b, 0x00c8, 0x31d1, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, - 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x0078, 0x1f03, - 0x0078, 0x2f75, 0x7033, 0x0000, 0xa282, 0x0006, 0x0050, 0x2b22, - 0x1078, 0x1eac, 0x2300, 0x0079, 0x2b25, 0x2b28, 0x2b4e, 0x2b72, - 0x2200, 0x0079, 0x2b2b, 0x2b31, 0x2f75, 0x2b33, 0x2b31, 0x2b9c, - 0x2bed, 0x1078, 0x1eac, 0x7003, 0x0005, 0x2001, 0x4390, 0x2068, - 0x703e, 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, - 0x2b43, 0x0078, 0x2b3c, 0x157f, 0x6817, 0x0000, 0x68b7, 0x0700, - 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x2f69, 0x7000, 0xa086, - 0x0001, 0x00c0, 0x2b5b, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034, - 0x600a, 0x0078, 0x2b60, 0x7000, 0xa086, 0x0003, 0x0040, 0x2b55, - 0x7003, 0x0005, 0x2001, 0x4390, 0x2068, 0x703e, 0x7032, 0x2200, - 0x0079, 0x2b6a, 0x2f75, 0x2b70, 0x2b70, 0x2b9c, 0x2b70, 0x2f75, - 0x1078, 0x1eac, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2b7f, 0x1078, - 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a, 0x0078, 0x2b84, 0x7000, - 0xa086, 0x0003, 0x0040, 0x2b79, 0x7003, 0x0005, 0x2001, 0x4390, - 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x2b8e, 0x2b96, 0x2b94, - 0x2b94, 0x2b96, 0x2b94, 0x2b96, 0x1078, 0x1eac, 0x1078, 0x2f8d, - 0x781b, 0x0067, 0x0078, 0x1efb, 0x7000, 0xa086, 0x0001, 0x00c0, - 0x2ba9, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a, 0x0078, - 0x2bae, 0x7000, 0xa086, 0x0003, 0x0040, 0x2ba3, 0x7003, 0x0002, - 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, - 0xa215, 0x2069, 0x4380, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, - 0x0040, 0x2bc9, 0x6814, 0xa206, 0x0040, 0x2be2, 0x6800, 0x0078, - 0x2bbc, 0x7003, 0x0005, 0x2001, 0x4390, 0x2068, 0x703e, 0x7032, - 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, 0x2bda, - 0x0078, 0x2bd3, 0x157f, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, + 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x0078, 0x2461, + 0x0078, 0x367b, 0x7037, 0x0000, 0xa282, 0x0006, 0x0050, 0x31ea, + 0x1078, 0x23ca, 0x7000, 0xa084, 0x0007, 0x10c0, 0x398a, 0x2300, + 0x0079, 0x31f2, 0x31f5, 0x321e, 0x3232, 0x2200, 0x0079, 0x31f8, + 0x321c, 0x367b, 0x31fe, 0x321c, 0x324e, 0x3290, 0x7003, 0x0005, + 0x2001, 0x7510, 0x2068, 0x704a, 0x157e, 0x20a9, 0x0031, 0x2003, + 0x0000, 0x8000, 0x0070, 0x320e, 0x0078, 0x3207, 0x157f, 0xad80, + 0x0009, 0x7036, 0x6817, 0x0000, 0x68b7, 0x0700, 0x6823, 0x0800, + 0x6827, 0x0003, 0x0078, 0x366b, 0x1078, 0x23ca, 0x7003, 0x0005, + 0x2001, 0x7510, 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200, + 0x0079, 0x322a, 0x367b, 0x3230, 0x3230, 0x324e, 0x3230, 0x367b, + 0x1078, 0x23ca, 0x7003, 0x0005, 0x2001, 0x7510, 0x2068, 0x704a, + 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x323e, 0x3246, 0x3244, + 0x3244, 0x3246, 0x3244, 0x3246, 0x1078, 0x23ca, 0x1078, 0x369f, + 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7003, 0x0002, + 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, + 0xa215, 0x2069, 0x7400, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005, + 0x0040, 0x3269, 0x6814, 0xa206, 0x0040, 0x3285, 0x6800, 0x0078, + 0x325c, 0x7003, 0x0005, 0x2001, 0x7510, 0x2068, 0x704a, 0x7036, + 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x327a, + 0x0078, 0x3273, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7, + 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820, + 0xa084, 0x0c00, 0x0040, 0x32df, 0x1078, 0x3697, 0x0078, 0x32df, + 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, + 0xa484, 0x001f, 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, + 0x7300, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005, 0x0040, 0x32af, + 0x6814, 0xa206, 0x0040, 0x32ca, 0x6800, 0x0078, 0x32a2, 0x7003, + 0x0005, 0x2001, 0x7510, 0x2068, 0x704a, 0x157e, 0x20a9, 0x0031, + 0x2003, 0x0000, 0x8000, 0x0070, 0x32bf, 0x0078, 0x32b8, 0x157f, + 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, - 0x2c4b, 0x1078, 0x2f85, 0x0078, 0x2c4b, 0x7000, 0xa086, 0x0001, - 0x00c0, 0x2bfa, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a, - 0x0078, 0x2bff, 0x7000, 0xa086, 0x0003, 0x0040, 0x2bf4, 0x7003, - 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, - 0x0007, 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x4280, - 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x2c1e, 0x6814, - 0xa206, 0x0040, 0x2c36, 0x6800, 0x0078, 0x2c11, 0x7003, 0x0005, - 0x2001, 0x4390, 0x2068, 0x703e, 0x157e, 0x20a9, 0x002f, 0x2003, - 0x0000, 0x8000, 0x0070, 0x2c2e, 0x0078, 0x2c27, 0x157f, 0x6a16, - 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, - 0x6820, 0xa084, 0x0c00, 0x0040, 0x2c4b, 0xa084, 0x0800, 0x0040, - 0x2c45, 0x1078, 0x2f89, 0x0078, 0x2c4b, 0x1078, 0x2f85, 0x70bf, - 0x0000, 0x0078, 0x2c4b, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, - 0x8003, 0x8003, 0xa080, 0x3a00, 0x2060, 0x704a, 0x6000, 0x704e, - 0x6004, 0x7052, 0xa684, 0x0060, 0x0040, 0x2c64, 0x68a8, 0x78d2, - 0x78da, 0x68a4, 0x78d6, 0x78de, 0x077f, 0x1078, 0x3099, 0x2009, - 0x0068, 0xa684, 0x0008, 0x0040, 0x2c6f, 0x2009, 0x0067, 0xa6b5, - 0x2000, 0x7e5a, 0x791a, 0xa684, 0x0060, 0x0040, 0x2c85, 0xa684, - 0x0800, 0x00c0, 0x2c7f, 0x1078, 0x3571, 0x0078, 0x2c85, 0xa684, - 0x4000, 0x00c0, 0x2c85, 0x1078, 0x3502, 0x2d00, 0x703e, 0x8207, - 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3a00, 0x2048, - 0x0078, 0x1efb, 0x6020, 0xa005, 0x0040, 0x2c9e, 0x8001, 0x6022, - 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006, - 0x1078, 0x32f5, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040, - 0x681f, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x2caf, 0x2cb7, - 0x2cb9, 0x2cb9, 0x2cc5, 0x2cc1, 0x2cb7, 0x2cc1, 0x2cb7, 0x1078, - 0x1eac, 0x1078, 0x2cd0, 0x1078, 0x2cc9, 0x1078, 0x1a26, 0x0078, - 0x1f03, 0x70a3, 0x0000, 0x0078, 0x1f03, 0x681b, 0x0000, 0x0078, - 0x2871, 0x6800, 0xa005, 0x00c0, 0x2cce, 0x6002, 0x6006, 0x007c, - 0x6010, 0xa005, 0x0040, 0x2cd9, 0x8001, 0x00d0, 0x2cd9, 0x1078, - 0x1eac, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, - 0xa005, 0x0040, 0x2ce5, 0x8001, 0x601a, 0x007c, 0x1078, 0x316a, - 0x6818, 0xa084, 0x8000, 0x0040, 0x2cef, 0x681b, 0x0018, 0x0078, - 0x2d26, 0x1078, 0x316a, 0x6818, 0xa084, 0x8000, 0x0040, 0x2cfa, - 0x681b, 0x0019, 0x0078, 0x2d26, 0x1078, 0x316a, 0x6818, 0xa084, - 0x8000, 0x0040, 0x2d05, 0x681b, 0x001a, 0x0078, 0x2d26, 0x1078, - 0x316a, 0x681b, 0x0003, 0x0078, 0x2d26, 0x71b8, 0xa18c, 0x00ff, - 0xa1e8, 0x4280, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2d1a, - 0x0078, 0x1f03, 0x6814, 0x72b4, 0xa206, 0x0040, 0x2d22, 0x6800, - 0x0078, 0x2d13, 0x6800, 0x200a, 0x681b, 0x0005, 0x681f, 0x0000, - 0x6823, 0x0020, 0x1078, 0x2cd0, 0x1078, 0x2cc9, 0x1078, 0x1a26, - 0x0078, 0x1f03, 0xa282, 0x0003, 0x00c0, 0x2f69, 0x7da8, 0xa5ac, - 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xa18d, 0x0080, 0x6922, - 0xa184, 0x0100, 0x0040, 0x2d92, 0xa18c, 0xfeff, 0x6922, 0xa6b4, - 0x00ff, 0x0040, 0x2d7c, 0xa682, 0x000c, 0x0048, 0x2d53, 0x0040, - 0x2d53, 0x2031, 0x000c, 0x852b, 0x852b, 0x1078, 0x3018, 0x0040, - 0x2d5d, 0x1078, 0x2e4a, 0x0078, 0x2d85, 0x1078, 0x2fd3, 0x0c7e, - 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2e6e, 0x0c7f, - 0x6920, 0xa18d, 0x0100, 0x6922, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, - 0xa684, 0x0400, 0x00c0, 0x2d78, 0x781b, 0x0053, 0x0078, 0x1efb, - 0x781b, 0x0067, 0x0078, 0x1efb, 0x0c7e, 0x2960, 0x6004, 0xa084, - 0xfff5, 0x6006, 0x1078, 0x2e6e, 0x0c7f, 0x7e58, 0xa684, 0x0400, - 0x00c0, 0x2d8e, 0x781b, 0x0056, 0x0078, 0x1efb, 0x781b, 0x0068, - 0x0078, 0x1efb, 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, - 0x0040, 0x2dd2, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, - 0x0048, 0x2da6, 0x0040, 0x2da6, 0x2011, 0x000c, 0x2600, 0xa202, - 0x00c8, 0x2dab, 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, - 0x0028, 0x00c0, 0x2dbb, 0xa282, 0x0019, 0x00c8, 0x2dc1, 0x2011, - 0x0019, 0x0078, 0x2dc1, 0xa282, 0x000c, 0x00c8, 0x2dc1, 0x2011, - 0x000c, 0x2200, 0xa502, 0x00c8, 0x2dc6, 0x2228, 0x1078, 0x2fd7, - 0x852b, 0x852b, 0x1078, 0x3018, 0x0040, 0x2dd2, 0x1078, 0x2e4a, - 0x0078, 0x2dd6, 0x1078, 0x2fd3, 0x1078, 0x2e6e, 0x7858, 0xa085, - 0x0004, 0x785a, 0x0c7f, 0x781b, 0x0067, 0x0078, 0x1efb, 0x0c7e, - 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x2df7, 0x6010, 0xa084, - 0x000f, 0x00c0, 0x2df1, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f, - 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x2e1e, 0x68a0, - 0xa084, 0x0200, 0x00c0, 0x2df1, 0x6208, 0xa294, 0x00ff, 0x7018, - 0xa086, 0x0028, 0x00c0, 0x2e0c, 0xa282, 0x0019, 0x00c8, 0x2e12, - 0x2011, 0x0019, 0x0078, 0x2e12, 0xa282, 0x000c, 0x00c8, 0x2e12, + 0x32df, 0xa084, 0x0800, 0x0040, 0x32d9, 0x1078, 0x369b, 0x0078, + 0x32df, 0x1078, 0x3697, 0x708b, 0x0000, 0x0078, 0x32df, 0x027e, + 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x5280, + 0x2060, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e, 0xa684, 0x0060, + 0x0040, 0x3337, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, + 0x3319, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a, + 0xa684, 0x0060, 0xa086, 0x0060, 0x0040, 0x3337, 0x68c0, 0xa005, + 0x0040, 0x3312, 0x7003, 0x0003, 0x682b, 0x0000, 0x1078, 0x48e6, + 0x0078, 0x3314, 0x1078, 0x48f7, 0xa6b5, 0x2000, 0x7e5a, 0x0078, + 0x3337, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, + 0x3337, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xa6b4, 0xbfff, + 0x7e5a, 0x007e, 0x68c0, 0xa005, 0x007f, 0x0040, 0x3335, 0x7003, + 0x0003, 0x1078, 0x48e6, 0x0078, 0x3337, 0x1078, 0x4942, 0x077f, + 0x1078, 0x37bd, 0x2009, 0x0065, 0xa684, 0x0004, 0x0040, 0x3358, + 0x78e4, 0xa084, 0x0030, 0x0040, 0x3350, 0x78ec, 0xa084, 0x0003, + 0x0040, 0x3350, 0x782b, 0x3008, 0x2009, 0x0065, 0x0078, 0x3358, + 0x0f7e, 0x2079, 0x5000, 0x1078, 0x4633, 0x0f7f, 0x0040, 0x2461, + 0x791a, 0x2d00, 0x704a, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, + 0x8003, 0xa080, 0x5280, 0x2048, 0x0078, 0x2438, 0x6020, 0xa005, + 0x0040, 0x3372, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, + 0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x4633, 0x6817, 0x0000, + 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, + 0x0007, 0x0079, 0x3383, 0x2461, 0x338d, 0x338d, 0x33aa, 0x3395, + 0x3393, 0x3395, 0x338b, 0x1078, 0x23ca, 0x1078, 0x33b5, 0x1078, + 0x33ae, 0x1078, 0x1c53, 0x0078, 0x2461, 0x706c, 0x706f, 0x0000, + 0x7093, 0x0000, 0x0079, 0x339c, 0x33a6, 0x33a6, 0x33a4, 0x33a4, + 0x33a4, 0x33a6, 0x33a4, 0x33a6, 0x0079, 0x2840, 0x706f, 0x0000, + 0x0078, 0x2461, 0x681b, 0x0000, 0x0078, 0x2eed, 0x6800, 0xa005, + 0x00c0, 0x33b3, 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, + 0x33be, 0x8001, 0x00d0, 0x33be, 0x1078, 0x23ca, 0x6012, 0x6008, + 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x33ca, + 0x8001, 0x601a, 0x007c, 0x1078, 0x38de, 0x681b, 0x0018, 0x0078, + 0x3401, 0x1078, 0x38de, 0x681b, 0x0019, 0x0078, 0x3401, 0x1078, + 0x38de, 0x681b, 0x001a, 0x0078, 0x3401, 0x1078, 0x38de, 0x681b, + 0x0003, 0x0078, 0x3401, 0x7780, 0x1078, 0x37bd, 0x7184, 0xa18c, + 0x00ff, 0xa1e8, 0x7300, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, + 0x33f3, 0x0078, 0x2461, 0x6814, 0x7280, 0xa206, 0x0040, 0x33fb, + 0x6800, 0x0078, 0x33ec, 0x6800, 0x200a, 0x681b, 0x0005, 0x708b, + 0x0000, 0x1078, 0x33b5, 0x6820, 0xa084, 0x0001, 0x00c0, 0x340a, + 0x1078, 0x33ae, 0x1078, 0x33c4, 0x681f, 0x0000, 0x6823, 0x0020, + 0x1078, 0x1c53, 0x0078, 0x2461, 0xa282, 0x0003, 0x00c0, 0x366b, + 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0x6920, 0xa18d, + 0x0080, 0x6922, 0xa184, 0x0100, 0x0040, 0x3478, 0xa18c, 0xfeff, + 0x6922, 0xa4a4, 0x00ff, 0x0040, 0x3462, 0xa482, 0x000c, 0x0048, + 0x3435, 0x0040, 0x3435, 0x2021, 0x000c, 0x852b, 0x852b, 0x1078, + 0x372e, 0x0040, 0x343f, 0x1078, 0x3531, 0x0078, 0x346b, 0x1078, + 0x36e9, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, + 0x3558, 0x0c7f, 0x6920, 0xa18d, 0x0100, 0x6922, 0x7e58, 0xa6b5, + 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x345c, 0x782b, 0x3008, + 0x781b, 0x0056, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0065, + 0x0078, 0x2438, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, + 0x1078, 0x3558, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x3474, + 0x781b, 0x0058, 0x0078, 0x2438, 0x781b, 0x0065, 0x0078, 0x2438, + 0x0c7e, 0x7054, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040, 0x34b8, + 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x348c, + 0x0040, 0x348c, 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8, 0x3491, + 0x2220, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, + 0x34a1, 0xa282, 0x0019, 0x00c8, 0x34a7, 0x2011, 0x0019, 0x0078, + 0x34a7, 0xa282, 0x000c, 0x00c8, 0x34a7, 0x2011, 0x000c, 0x2200, + 0xa502, 0x00c8, 0x34ac, 0x2228, 0x1078, 0x36ed, 0x852b, 0x852b, + 0x1078, 0x372e, 0x0040, 0x34b8, 0x1078, 0x3531, 0x0078, 0x34bc, + 0x1078, 0x36e9, 0x1078, 0x3558, 0x7858, 0xa085, 0x0004, 0x785a, + 0x0c7f, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x0c7e, + 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x34df, 0x6010, 0xa084, + 0x000f, 0x00c0, 0x34d9, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f, + 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3506, 0x68a0, + 0xa084, 0x0200, 0x00c0, 0x34d9, 0x6208, 0xa294, 0x00ff, 0x7018, + 0xa086, 0x0028, 0x00c0, 0x34f4, 0xa282, 0x0019, 0x00c8, 0x34fa, + 0x2011, 0x0019, 0x0078, 0x34fa, 0xa282, 0x000c, 0x00c8, 0x34fa, 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, - 0x0048, 0x2e1e, 0x0040, 0x2e1e, 0x2019, 0x000c, 0x78ab, 0x0001, + 0x0048, 0x3506, 0x0040, 0x3506, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x2960, - 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, - 0x0078, 0x2e3a, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, - 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, - 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084, 0xfff0, - 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, - 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a, 0xa6b4, - 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, - 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7048, - 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, - 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282, 0x0002, - 0x00c0, 0x2f69, 0x7aa8, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, - 0x0200, 0x0040, 0x2ec3, 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, - 0xa282, 0x0002, 0x00c8, 0x2f69, 0x1078, 0x2f0a, 0x1078, 0x2e6e, - 0xa980, 0x0001, 0x200c, 0x1078, 0x3095, 0x1078, 0x2ddf, 0x88ff, - 0x0040, 0x2eb6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, - 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2eb2, 0x781b, 0x0053, - 0x0078, 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb, 0x7e58, 0xa684, - 0x0400, 0x00c0, 0x2ebf, 0x781b, 0x0056, 0x0078, 0x1efb, 0x781b, - 0x0068, 0x0078, 0x1efb, 0xa282, 0x0002, 0x00c8, 0x2ecb, 0xa284, - 0x0001, 0x0040, 0x2ed5, 0x7148, 0xa188, 0x0000, 0x210c, 0xa18c, - 0x2000, 0x00c0, 0x2ed5, 0x2011, 0x0000, 0x1078, 0x2fc5, 0x1078, - 0x2f0a, 0x1078, 0x2e6e, 0x7858, 0xa085, 0x0004, 0x785a, 0x781b, - 0x0067, 0x0078, 0x1efb, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, - 0x0001, 0xa084, 0x2000, 0x00c0, 0x2efa, 0x6014, 0xa084, 0x0040, - 0x00c0, 0x2ef8, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x2f07, - 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, - 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f, - 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040, 0x2f12, - 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, - 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef, - 0x6006, 0x0c7f, 0x007c, 0xa684, 0x0020, 0x0040, 0x2f65, 0x7888, - 0xa084, 0x0040, 0x0040, 0x2f65, 0x7bb8, 0xa384, 0x003f, 0x831b, - 0x00c8, 0x2f33, 0x8000, 0xa005, 0x0040, 0x2f4c, 0x831b, 0x00c8, - 0x2f3c, 0x8001, 0x0040, 0x2f61, 0xa684, 0x4000, 0x0040, 0x2f4c, - 0x78b8, 0x801b, 0x00c8, 0x2f45, 0x8000, 0xa084, 0x003f, 0x00c0, - 0x2f61, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, - 0xa108, 0x00c8, 0x2f55, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, - 0x7ade, 0x1078, 0x362f, 0x781b, 0x0065, 0x1078, 0x3502, 0x0078, - 0x1efb, 0x781b, 0x0065, 0x0078, 0x1efb, 0x781b, 0x0068, 0x0078, - 0x1efb, 0x1078, 0x2f91, 0x781b, 0x0067, 0x0078, 0x1efb, 0x1078, - 0x2f7d, 0x781b, 0x0067, 0x0078, 0x1efb, 0x6827, 0x0002, 0x1078, - 0x2f85, 0x781b, 0x0067, 0x0078, 0x1efb, 0x2001, 0x0005, 0x0078, - 0x2f93, 0x2001, 0x000c, 0x0078, 0x2f93, 0x2001, 0x0006, 0x0078, - 0x2f93, 0x2001, 0x000d, 0x0078, 0x2f93, 0x2001, 0x0009, 0x0078, - 0x2f93, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xa6b5, 0x0008, - 0x7e5a, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, - 0x8703, 0xa0e0, 0x3a00, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, - 0x000f, 0x0040, 0x2fb3, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, - 0xa085, 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, - 0x0040, 0x0040, 0x2fc3, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, - 0xa085, 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, - 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, - 0x78ab, 0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, - 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, - 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, - 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, - 0xa18c, 0xfff0, 0x2001, 0x3946, 0x2004, 0xa082, 0x0028, 0x0040, - 0x3001, 0x2021, 0x307c, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, - 0x3007, 0x2021, 0x3088, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, - 0x0064, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x3016, 0x8420, - 0x2300, 0xa210, 0x0070, 0x3016, 0x0078, 0x3009, 0x157f, 0x007c, - 0x157e, 0x2011, 0x3946, 0x2214, 0xa282, 0x0032, 0x0048, 0x302c, - 0x0040, 0x3030, 0x2021, 0x306e, 0x2019, 0x0011, 0x20a9, 0x000e, - 0x2011, 0x0032, 0x0078, 0x3042, 0xa282, 0x0028, 0x0040, 0x303a, - 0x2021, 0x307c, 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, - 0x0078, 0x3042, 0x2021, 0x3088, 0x2019, 0x0019, 0x20a9, 0x000d, - 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x3052, 0x0048, 0x3052, - 0x8420, 0x2300, 0xa210, 0x0070, 0x304f, 0x0078, 0x3042, 0x157f, - 0xa006, 0x007c, 0x157f, 0x7a08, 0xa582, 0x0064, 0x00c8, 0x305d, - 0xa285, 0x0040, 0x780a, 0x0078, 0x305d, 0x78ec, 0xa084, 0x0300, - 0x0040, 0x306b, 0x2404, 0xa09e, 0x2002, 0x00c0, 0x306b, 0x2001, - 0x2101, 0x0078, 0x306c, 0x2404, 0xa015, 0x007c, 0x2002, 0x3002, - 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, - 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202, - 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05, - 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604, - 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046, - 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003, - 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3a80, 0x007c, 0x79d8, 0x7adc, - 0x78d0, 0x801b, 0x00c8, 0x30ad, 0x8000, 0xa084, 0x003f, 0xa108, - 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3940, - 0x2091, 0x8000, 0x2104, 0x0079, 0x30bd, 0x30e3, 0x30c7, 0x30c7, - 0x30c7, 0x30c7, 0x30c7, 0x30c7, 0x30c5, 0x1078, 0x1eac, 0x784b, - 0x0004, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000, - 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x30e3, 0x0018, 0x30e3, - 0x681c, 0xa084, 0x0020, 0x00c0, 0x30e1, 0x781b, 0x00df, 0x0078, - 0x30e3, 0x781b, 0x00e6, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x0c7e, + 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, + 0x3521, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, + 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, + 0x007c, 0x0c7e, 0x7154, 0x2160, 0x1078, 0x3538, 0x0c7f, 0x007c, + 0x2008, 0xa084, 0xfff0, 0xa425, 0x7c86, 0x6018, 0x789a, 0x7cae, + 0x6412, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, + 0x6016, 0x788a, 0xa4a4, 0x000f, 0x8427, 0x8204, 0x8004, 0xa084, + 0x00ff, 0xa405, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, 0x007c, + 0x0c7e, 0x7054, 0x2060, 0x1078, 0x355f, 0x0c7f, 0x007c, 0x6018, + 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, + 0xfff0, 0x7886, 0x007c, 0xa282, 0x0002, 0x00c0, 0x366b, 0x7aa8, + 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0200, 0x0040, 0x35b4, + 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, + 0x366b, 0x1078, 0x35fd, 0x1078, 0x3558, 0xa980, 0x0001, 0x200c, + 0x1078, 0x37b9, 0x1078, 0x34c7, 0x88ff, 0x0040, 0x35a7, 0x789b, + 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, + 0x0400, 0x00c0, 0x35a1, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, + 0x2438, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7e58, + 0xa684, 0x0400, 0x00c0, 0x35b0, 0x781b, 0x0058, 0x0078, 0x2438, + 0x781b, 0x0065, 0x0078, 0x2438, 0xa282, 0x0002, 0x00c8, 0x35bc, + 0xa284, 0x0001, 0x0040, 0x35c6, 0x7154, 0xa188, 0x0000, 0x210c, + 0xa18c, 0x2000, 0x00c0, 0x35c6, 0x2011, 0x0000, 0x1078, 0x36db, + 0x1078, 0x35fd, 0x1078, 0x3558, 0x7858, 0xa085, 0x0004, 0x785a, + 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x0c7e, 0x027e, + 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x35ed, + 0x6014, 0xa084, 0x0040, 0x00c0, 0x35eb, 0xa18c, 0xffef, 0x6106, + 0xa006, 0x0078, 0x35fa, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, + 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085, + 0x0200, 0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7054, 0x2060, + 0x1078, 0x3604, 0x0c7f, 0x007c, 0x82ff, 0x0040, 0x3609, 0x2011, + 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, + 0xa205, 0x78a6, 0x788a, 0x6016, 0x6004, 0xa084, 0xffef, 0x6006, + 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3622, 0x007f, + 0x0078, 0x3625, 0x007f, 0x0078, 0x3667, 0xa684, 0x0020, 0x0040, + 0x3667, 0x7888, 0xa084, 0x0040, 0x0040, 0x3667, 0x7bb8, 0xa384, + 0x003f, 0x831b, 0x00c8, 0x3635, 0x8000, 0xa005, 0x0040, 0x364b, + 0x831b, 0x00c8, 0x363e, 0x8001, 0x0040, 0x3663, 0xa684, 0x4000, + 0x0040, 0x364b, 0x78b8, 0x801b, 0x00c8, 0x3647, 0x8000, 0xa084, + 0x003f, 0x00c0, 0x3663, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, + 0x2001, 0x0001, 0xa108, 0x00c8, 0x3657, 0xa291, 0x0000, 0x79d2, + 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x49ed, 0x781b, 0x0064, 0x1078, + 0x4872, 0x0078, 0x2438, 0x781b, 0x0064, 0x0078, 0x2438, 0x781b, + 0x0065, 0x0078, 0x2438, 0x1078, 0x36a3, 0x782b, 0x3008, 0x781b, + 0x0065, 0x0078, 0x2438, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b, + 0x0065, 0x0078, 0x2438, 0x6827, 0x0002, 0x1078, 0x3697, 0x78e4, + 0xa084, 0x0030, 0x0040, 0x2461, 0x78ec, 0xa084, 0x0003, 0x0040, + 0x2461, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x2001, + 0x0005, 0x0078, 0x36a5, 0x2001, 0x000c, 0x0078, 0x36a5, 0x2001, + 0x0006, 0x0078, 0x36a5, 0x2001, 0x000d, 0x0078, 0x36a5, 0x2001, + 0x0009, 0x0078, 0x36a5, 0x2001, 0x0007, 0x789b, 0x0010, 0x78aa, + 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004, 0x7e5a, 0x007c, + 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, + 0x5280, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, + 0x36c9, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008, + 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040, + 0x36d9, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010, + 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, + 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004, + 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, + 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, + 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, + 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, + 0x2001, 0x5046, 0x2004, 0xa082, 0x0028, 0x0040, 0x3717, 0x2021, + 0x37a0, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x371d, 0x2021, + 0x37ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404, + 0xa084, 0xfff0, 0xa106, 0x0040, 0x372c, 0x8420, 0x2300, 0xa210, + 0x0070, 0x372c, 0x0078, 0x371f, 0x157f, 0x007c, 0x157e, 0x2009, + 0x5046, 0x210c, 0xa182, 0x0032, 0x0048, 0x3742, 0x0040, 0x3746, + 0x2009, 0x3792, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, + 0x0078, 0x3758, 0xa182, 0x0028, 0x0040, 0x3750, 0x2009, 0x37a0, + 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, 0x0078, 0x3758, + 0x2009, 0x37ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, + 0x2200, 0xa502, 0x0040, 0x3768, 0x0048, 0x3768, 0x8108, 0x2300, + 0xa210, 0x0070, 0x3765, 0x0078, 0x3758, 0x157f, 0xa006, 0x007c, + 0x157f, 0xa582, 0x0064, 0x00c8, 0x3777, 0x7808, 0xa085, 0x0070, + 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078, 0x3777, 0x78ec, + 0xa084, 0x0300, 0x0040, 0x377f, 0x2104, 0x0078, 0x3790, 0x2104, + 0xa09e, 0x1102, 0x00c0, 0x3790, 0x2001, 0x04fd, 0x2004, 0xa082, + 0x0005, 0x0048, 0x378f, 0x2001, 0x1201, 0x0078, 0x3790, 0x2104, + 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, + 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07, + 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, + 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, + 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, + 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800b, + 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, + 0x5300, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x37d1, + 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, + 0x2079, 0x0100, 0x2009, 0x5040, 0x2091, 0x8000, 0x2104, 0x0079, + 0x37e1, 0x3817, 0x37eb, 0x37eb, 0x37eb, 0x37eb, 0x37eb, 0x37eb, + 0x381b, 0x1078, 0x23ca, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, + 0x00c0, 0x37ed, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0, + 0x37f4, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000, + 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3817, 0x0018, 0x3817, + 0x681c, 0xa084, 0x0020, 0x00c0, 0x3815, 0x0e7e, 0x2071, 0x5040, + 0x1078, 0x3868, 0x0e7f, 0x0078, 0x3817, 0x781b, 0x00d2, 0x2091, + 0x8001, 0x0f7f, 0x007c, 0x1078, 0x3a42, 0x0078, 0x3817, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, - 0x3a00, 0x6004, 0xa084, 0x000a, 0x00c0, 0x311a, 0x6108, 0xa194, - 0xff00, 0x0040, 0x311a, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, - 0x0040, 0x3109, 0x2001, 0x0032, 0xa106, 0x0040, 0x310d, 0x0078, - 0x3111, 0x2009, 0x0020, 0x0078, 0x3113, 0x2009, 0x003f, 0x0078, - 0x3113, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, - 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0068, 0x0078, 0x1efb, - 0x781b, 0x0067, 0x0078, 0x1efb, 0x781b, 0x0056, 0x0078, 0x1efb, - 0x781b, 0x0053, 0x0078, 0x1efb, 0x781b, 0x00df, 0x0078, 0x1efb, - 0x781b, 0x00de, 0x0078, 0x1efb, 0x781b, 0x00e6, 0x0078, 0x1efb, - 0x781b, 0x00e5, 0x0078, 0x1efb, 0x781b, 0x009d, 0x0078, 0x1efb, - 0x781b, 0x009c, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040, - 0x314b, 0x681b, 0x001d, 0x70a3, 0x0001, 0x781b, 0x0047, 0x0078, - 0x1efb, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3168, 0x7808, - 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, - 0xa084, 0x0021, 0x0040, 0x3168, 0x7808, 0xa085, 0x0002, 0x780a, - 0x007f, 0x007c, 0x7808, 0xa085, 0x0002, 0x780a, 0x007c, 0x7830, - 0xa084, 0x0040, 0x00c0, 0x316f, 0x0098, 0x3178, 0x78ac, 0x007c, + 0x5280, 0x6004, 0xa084, 0x000a, 0x00c0, 0x3852, 0x6108, 0xa194, + 0xff00, 0x0040, 0x3852, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, + 0x0040, 0x3841, 0x2001, 0x0032, 0xa106, 0x0040, 0x3845, 0x0078, + 0x3849, 0x2009, 0x0020, 0x0078, 0x384b, 0x2009, 0x003f, 0x0078, + 0x384b, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, + 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0065, 0x0078, 0x2438, + 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x781b, 0x0058, + 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, + 0x2009, 0x5020, 0x210c, 0xa186, 0x0000, 0x0040, 0x387c, 0xa186, + 0x0001, 0x0040, 0x387f, 0x2009, 0x5038, 0x200b, 0x000b, 0x706f, + 0x0001, 0x781b, 0x0048, 0x007c, 0x781b, 0x00cc, 0x007c, 0x2009, + 0x5038, 0x200b, 0x000a, 0x007c, 0x2009, 0x5020, 0x210c, 0xa186, + 0x0000, 0x0040, 0x389f, 0xa186, 0x0001, 0x0040, 0x3899, 0x2009, + 0x5038, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, + 0x2438, 0x2009, 0x5038, 0x200b, 0x000a, 0x0078, 0x2438, 0x782b, + 0x3008, 0x781b, 0x00cc, 0x0078, 0x2438, 0x781b, 0x00d2, 0x0078, + 0x2438, 0x782b, 0x3008, 0x781b, 0x00d2, 0x0078, 0x2438, 0x781b, + 0x0093, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0093, 0x0078, + 0x2438, 0x6818, 0xa084, 0x8000, 0x0040, 0x38c0, 0x681b, 0x001d, + 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, 0x2438, 0x007e, 0x7830, + 0xa084, 0x00c0, 0x00c0, 0x38dc, 0x7808, 0xa084, 0xfffc, 0x780a, + 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, + 0x38dc, 0x7044, 0x780a, 0xa005, 0x007f, 0x007c, 0x7044, 0xa085, + 0x0002, 0x7046, 0x780a, 0x007c, 0x007e, 0x7830, 0xa084, 0x0040, + 0x00c0, 0x38e5, 0x0098, 0x38f0, 0x007f, 0x789a, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, - 0x78ec, 0xa084, 0x0021, 0x0040, 0x3187, 0x0098, 0x3185, 0x78ac, - 0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, - 0x0070, 0x0040, 0x319b, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x1e57, - 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x31a8, 0x784b, - 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1f03, 0x0078, 0x311c, - 0xa784, 0x0004, 0x0040, 0x31db, 0x78b8, 0xa084, 0x4001, 0x0040, - 0x31db, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1f03, - 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x31db, 0x78c0, - 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00e6, 0x0078, 0x1efb, - 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040, 0x31d7, 0x681b, - 0x0015, 0xa684, 0x4000, 0x0040, 0x31d7, 0x681b, 0x0007, 0x781b, - 0x00df, 0x0078, 0x1efb, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, - 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78e4, - 0xa005, 0x00d0, 0x238a, 0xa084, 0x0020, 0x0040, 0x238a, 0x0018, - 0x238a, 0x0078, 0x2f6f, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, - 0x8003, 0x8003, 0xa080, 0x3a00, 0x2060, 0x2048, 0x704a, 0x6000, - 0x704e, 0x6004, 0x7052, 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, - 0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014, 0x98f9, 0x98e9, - 0x0014, 0x0014, 0x0080, 0x00c0, 0x0100, 0x0402, 0x2008, 0xf880, - 0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0xa200, 0x8838, - 0x3806, 0x8839, 0x28c2, 0x9cc2, 0xa805, 0x0864, 0xa83d, 0x3008, - 0x28c1, 0x9cc2, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, - 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9c9f, 0xa8f3, 0x0864, - 0xa82b, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9c9f, 0x280d, 0xa204, - 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, - 0xa80f, 0x786e, 0x883e, 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0, - 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa801, 0x883e, - 0x206b, 0x28c1, 0x9cc2, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc, - 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, 0x8000, 0x85a4, 0x1872, - 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, 0x0704, - 0x3008, 0x9c9f, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, - 0x19e2, 0xf848, 0x8174, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f, - 0x08e6, 0xa8f1, 0xf861, 0xa8e8, 0xf801, 0x0014, 0xf881, 0x0016, - 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, - 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0xa206, 0x6865, - 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa, - 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x11d6, - 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822, 0x0016, 0x8000, 0x2848, - 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd, - 0xa883, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017, 0x300c, - 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0xd301, 0x0014, 0x26e0, - 0x873a, 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, - 0x3806, 0x0210, 0x9ccc, 0x0704, 0x0000, 0x127e, 0x2091, 0x2200, - 0x2049, 0x32f5, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215, 0x7008, - 0xa084, 0xfff7, 0xa205, 0x0040, 0x3307, 0x1078, 0x3380, 0x127f, - 0x2000, 0x007c, 0x6428, 0x84ff, 0x0040, 0x3336, 0x2c70, 0x7004, - 0xa0bc, 0x000f, 0xa7b8, 0x3346, 0x273c, 0x87fb, 0x00c0, 0x3324, - 0x0048, 0x331c, 0x1078, 0x1eac, 0x609c, 0xa075, 0x0040, 0x3336, - 0x0078, 0x330f, 0x2039, 0x333b, 0x2704, 0xae68, 0x6808, 0xa630, - 0x680c, 0xa529, 0x8421, 0x0040, 0x3336, 0x8738, 0x2704, 0xa005, - 0x00c0, 0x3325, 0x709c, 0xa075, 0x00c0, 0x330f, 0x007c, 0x0000, - 0x0005, 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, - 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x333b, - 0x3338, 0x0000, 0x0000, 0x8000, 0x0000, 0x333b, 0x0000, 0x3343, - 0x3340, 0x0000, 0x0000, 0x0000, 0x0000, 0x3343, 0x0000, 0x333e, - 0x333e, 0x0000, 0x0000, 0x8000, 0x0000, 0x333e, 0x0000, 0x3344, - 0x3344, 0x0000, 0x0000, 0x0000, 0x0000, 0x3344, 0x127e, 0x2091, - 0x2200, 0x2079, 0x3900, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, - 0x0002, 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, - 0x0002, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, - 0x2049, 0x3380, 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x33b2, - 0x7007, 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x338a, 0xa184, - 0x01e0, 0x0040, 0x3395, 0x1078, 0x1eac, 0xa184, 0x4000, 0x00c0, - 0x338a, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x33a7, 0xa386, - 0x0008, 0x0040, 0x33b2, 0xa386, 0x200c, 0x00c0, 0x338a, 0x7200, - 0x8204, 0x0048, 0x33b2, 0x730c, 0xa384, 0x00ff, 0x0040, 0x33b2, - 0x1078, 0x1eac, 0x7007, 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, - 0x33c3, 0x7310, 0x7014, 0xa305, 0x0040, 0x33c3, 0x700c, 0xa084, - 0x00ff, 0x00c0, 0x3380, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, - 0xa084, 0x0008, 0x00c0, 0x33c7, 0x7007, 0x0012, 0x7108, 0x8103, - 0x0048, 0x33cc, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, - 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x33e7, - 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, - 0x7500, 0x730c, 0xa384, 0x0300, 0x00c0, 0x3426, 0xa184, 0x0060, - 0x00c0, 0x3442, 0x7008, 0x7108, 0xa106, 0x00c0, 0x33f2, 0xa184, - 0x01e0, 0x00c0, 0x3442, 0xa184, 0x4000, 0x00c0, 0x33f2, 0xa986, - 0x362f, 0x00c0, 0x341a, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, - 0x3411, 0xa386, 0x0008, 0x0040, 0x341a, 0xa386, 0x200c, 0x00c0, - 0x33f2, 0x7200, 0x8204, 0x0048, 0x341a, 0x730c, 0xa384, 0x00ff, - 0x00c0, 0x3426, 0xa184, 0x0007, 0x0079, 0x341e, 0x3428, 0x3436, - 0x3426, 0x3436, 0x3426, 0x348f, 0x3426, 0x348d, 0x1078, 0x1eac, - 0x7007, 0x0002, 0x8aff, 0x00c0, 0x3431, 0x2049, 0x0000, 0x0078, - 0x3435, 0x1078, 0x3606, 0x00c0, 0x3431, 0x007c, 0x7007, 0x0002, - 0x8aff, 0x00c0, 0x343d, 0x0078, 0x3441, 0x1078, 0x3606, 0x00c0, - 0x343d, 0x007c, 0x7108, 0x7008, 0xa106, 0x00c0, 0x3442, 0xa184, - 0x4000, 0x00c0, 0x3442, 0x7007, 0x0012, 0x7108, 0x7008, 0xa106, - 0x00c0, 0x344d, 0xa184, 0x4000, 0x00c0, 0x344d, 0x00e0, 0x3456, - 0x2091, 0x6000, 0x00e0, 0x345a, 0x2091, 0x6000, 0x7007, 0x0012, - 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x3462, 0x7007, - 0x0012, 0x7108, 0x8103, 0x0048, 0x3467, 0x7003, 0x0000, 0x7000, - 0xa005, 0x00c0, 0x347b, 0x7004, 0xa005, 0x00c0, 0x347b, 0x700c, - 0xa005, 0x0040, 0x347d, 0x0078, 0x345e, 0x2049, 0x0000, 0x1078, - 0x30b3, 0x6818, 0xa084, 0x8000, 0x0040, 0x3488, 0x681b, 0x0002, - 0x007c, 0x1078, 0x1eac, 0x1078, 0x1eac, 0x1078, 0x34ed, 0x7210, - 0x7114, 0x700c, 0xa09c, 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, - 0x0000, 0x1078, 0x34ed, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, - 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x34b2, - 0x00c8, 0x34b2, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, - 0x0078, 0x3499, 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, - 0x0040, 0x34be, 0xa7ba, 0x3340, 0x0078, 0x34c0, 0xa7ba, 0x3338, - 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x1078, - 0x3380, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x34dd, 0x609c, - 0xa005, 0x0040, 0x34ea, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, - 0x3346, 0x203c, 0x87fb, 0x1040, 0x1eac, 0x8a51, 0x0040, 0x34e9, - 0x7008, 0x7508, 0xa52e, 0x00c0, 0x34e0, 0xa084, 0x0003, 0xa086, + 0x78ec, 0xa084, 0x0021, 0x0040, 0x38ff, 0x0098, 0x38fd, 0x007f, + 0x789a, 0x78ac, 0x007e, 0x7044, 0x780a, 0x007f, 0x007c, 0x78ec, + 0xa084, 0x0002, 0x00c0, 0x461d, 0xa784, 0x007d, 0x00c0, 0x3913, + 0x2700, 0x1078, 0x23ca, 0xa784, 0x0001, 0x00c0, 0x2f43, 0xa784, + 0x0070, 0x0040, 0x3923, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x2375, + 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x3930, 0x784b, + 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2461, 0x0078, 0x3854, + 0xa784, 0x0004, 0x0040, 0x3963, 0x78b8, 0xa084, 0x4001, 0x0040, + 0x3963, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2461, + 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x3963, 0x78c0, + 0xa085, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00d2, 0x0078, 0x2438, + 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040, 0x395f, 0x681b, + 0x0015, 0xa684, 0x4000, 0x0040, 0x395f, 0x681b, 0x0007, 0x1078, + 0x3868, 0x0078, 0x2438, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, + 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, + 0xa084, 0x0003, 0x0040, 0x2944, 0x0018, 0x2438, 0x0078, 0x3673, + 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, + 0x5280, 0x2060, 0x2048, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e, + 0x2a60, 0x007c, 0x0079, 0x398c, 0x3994, 0x3995, 0x3994, 0x3997, + 0x3994, 0x3994, 0x3994, 0x399c, 0x007c, 0x1078, 0x33c4, 0x1078, + 0x4633, 0x7038, 0x600a, 0x007c, 0x70a0, 0xa005, 0x0040, 0x39a9, + 0x2068, 0x1078, 0x1b45, 0x1078, 0x45b5, 0x1078, 0x45bc, 0x70a3, + 0x0000, 0x007c, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x5040, 0x7000, + 0xa086, 0x0007, 0x00c0, 0x39c0, 0x6110, 0x70bc, 0xa106, 0x00c0, + 0x39c0, 0x0e7f, 0x1078, 0x1b52, 0x1078, 0x39c6, 0xa006, 0x007c, + 0x2091, 0x8001, 0x0e7f, 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, + 0x2071, 0x5040, 0x0078, 0x21d9, 0x785b, 0x0000, 0x70af, 0x000e, + 0x2009, 0x0100, 0x017e, 0x70a0, 0xa06d, 0x0040, 0x39db, 0x70a3, + 0x0000, 0x0078, 0x39e1, 0x70b3, 0x0000, 0x1078, 0x1b6e, 0x0040, + 0x39e7, 0x70ac, 0x6826, 0x1078, 0x3ac2, 0x0078, 0x39db, 0x017f, + 0x157e, 0x0c7e, 0x0d7e, 0x20a9, 0x0008, 0x2061, 0x7410, 0x6000, + 0xa105, 0x6002, 0x601c, 0xa06d, 0x0040, 0x39ff, 0x6800, 0x601e, + 0x1078, 0x193d, 0x6008, 0x8000, 0x600a, 0x0078, 0x39f2, 0x6018, + 0xa06d, 0x0040, 0x3a09, 0x6800, 0x601a, 0x1078, 0x193d, 0x0078, + 0x39ff, 0xace0, 0x0008, 0x0070, 0x3a0f, 0x0078, 0x39ef, 0x709c, + 0xa084, 0x8000, 0x0040, 0x3a16, 0x1078, 0x3b3c, 0x0d7f, 0x0c7f, + 0x157f, 0x007c, 0x127e, 0x2091, 0x2300, 0x6804, 0xa084, 0x000f, + 0x0079, 0x3a22, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32, + 0x3a34, 0x3a3a, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a3c, + 0x3a32, 0x3a34, 0x1078, 0x23ca, 0x1078, 0x4466, 0x1078, 0x193d, + 0x0078, 0x3a40, 0x6827, 0x000b, 0x1078, 0x4466, 0x1078, 0x3ac2, + 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x0098, 0x3a5e, 0x7830, + 0xa084, 0x00c0, 0x00c0, 0x3a5e, 0x0d7e, 0x1078, 0x45c5, 0x2d00, + 0x682e, 0x2009, 0x0004, 0x2001, 0x0000, 0x6827, 0x0084, 0x1078, + 0x457e, 0x1078, 0x3ac2, 0x0d7f, 0x0078, 0x3a90, 0x7948, 0xa185, + 0x4000, 0x784a, 0x0098, 0x3a67, 0x794a, 0x0078, 0x3a4c, 0x7828, + 0xa086, 0x1834, 0x00c0, 0x3a70, 0xa185, 0x0004, 0x0078, 0x3a77, + 0x7828, 0xa186, 0x1814, 0x00c0, 0x3a64, 0xa185, 0x000c, 0x784a, + 0x789b, 0x000e, 0x78ab, 0x0002, 0x7858, 0xa084, 0x00ff, 0xa085, + 0x0400, 0x785a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x6827, 0x0002, + 0x6827, 0x0084, 0x2009, 0x0004, 0x2001, 0x0000, 0x1078, 0x457e, + 0x127f, 0x007c, 0x0d7e, 0x6b14, 0x1078, 0x1be0, 0x0040, 0x3a9f, + 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0078, 0x3a94, 0x0d7f, + 0x007c, 0x0d7e, 0x6b14, 0x6c28, 0xa4a4, 0x00ff, 0x1078, 0x1b7e, + 0x0040, 0x3aaf, 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0d7f, + 0x007c, 0x0d7e, 0x6b14, 0xa39c, 0x00ff, 0x1078, 0x1bb1, 0x0040, + 0x3ac0, 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0078, 0x3ab5, + 0x0d7f, 0x007c, 0x0c7e, 0x6914, 0x1078, 0x3b33, 0x6904, 0xa18c, + 0x00ff, 0xa186, 0x0006, 0x0040, 0x3add, 0xa186, 0x000d, 0x0040, + 0x3afc, 0xa186, 0x0017, 0x00c0, 0x3ad9, 0x1078, 0x193d, 0x0078, + 0x3adb, 0x1078, 0x1c55, 0x0c7f, 0x007c, 0x6004, 0x8001, 0x0048, + 0x3afa, 0x6006, 0x2009, 0x0000, 0xa684, 0x0001, 0x00c0, 0x3aea, + 0xa18d, 0x8000, 0xa684, 0x0004, 0x0040, 0x3af0, 0xa18d, 0x0002, + 0x691e, 0x6823, 0x0000, 0x7104, 0x810f, 0x6818, 0xa105, 0x681a, + 0x0078, 0x3ad9, 0x1078, 0x23ca, 0x6018, 0xa005, 0x00c0, 0x3b0b, + 0x6008, 0x8001, 0x0048, 0x3b0b, 0x600a, 0x601c, 0x6802, 0x2d00, + 0x601e, 0x0078, 0x3b21, 0xac88, 0x0006, 0x2104, 0xa005, 0x0040, + 0x3b14, 0x2008, 0x0078, 0x3b0d, 0x6802, 0x2d0a, 0x6008, 0x8001, + 0x0048, 0x3adb, 0x600a, 0x6018, 0x2068, 0x6800, 0x601a, 0x0078, + 0x3b05, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0d7e, 0x1078, 0x191a, + 0x2da0, 0x137f, 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f, + 0x157f, 0x0078, 0x3ad9, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003, + 0xa080, 0x7410, 0x2060, 0x007c, 0x2019, 0x5051, 0x2304, 0xa085, + 0x0001, 0x201a, 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a, + 0x007c, 0x2019, 0x5051, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019, + 0x0102, 0x2304, 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c, + 0xfff8, 0x7992, 0x70b4, 0xa080, 0x00d8, 0x781a, 0x0078, 0x2438, + 0x70a3, 0x0000, 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000, + 0x0018, 0x23ef, 0x1078, 0x1b6e, 0x0040, 0x3b91, 0x2009, 0x500f, + 0x200b, 0x0000, 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040, + 0x3b85, 0x6827, 0x000e, 0xa084, 0x0200, 0x0040, 0x3b81, 0x6827, + 0x0017, 0x1078, 0x3ac2, 0x0078, 0x3b60, 0x7000, 0xa086, 0x0007, + 0x00c0, 0x3be3, 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078, + 0x3b98, 0x7040, 0xa086, 0x0001, 0x0040, 0x2471, 0x0078, 0x2438, + 0x2031, 0x0000, 0x691c, 0xa184, 0x0002, 0x0040, 0x3ba1, 0xa6b5, + 0x0004, 0xa184, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3c72, + 0x2004, 0xa635, 0x6820, 0xa084, 0x0400, 0x0040, 0x3bb9, 0x789b, + 0x0018, 0x78ab, 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, + 0x1000, 0x6820, 0xa084, 0x8000, 0x0040, 0x3bc5, 0xa6b5, 0x0400, + 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0xa684, 0x0200, 0x0040, + 0x3bdf, 0x682c, 0x78d2, 0x6830, 0x78d6, 0xa684, 0x0100, 0x0040, + 0x3bdd, 0x682c, 0xa084, 0x0001, 0x0040, 0x3bdd, 0x7888, 0xa084, + 0x0040, 0x0040, 0x3bdd, 0xa6b5, 0x8000, 0x1078, 0x45ad, 0x7e5a, + 0x6eb6, 0x0078, 0x45e4, 0x1078, 0x38c6, 0x00c0, 0x3c6c, 0x702c, + 0x8004, 0x0048, 0x3bf1, 0x2019, 0x4cfd, 0x1078, 0x2255, 0x702f, + 0x0001, 0x2011, 0x0001, 0x2031, 0x1000, 0x789b, 0x0018, 0x6814, + 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x691c, 0xa184, 0x0002, + 0x0040, 0x3c0a, 0xa6b5, 0x0004, 0x78ab, 0x0020, 0x6828, 0x78aa, + 0xa290, 0x0002, 0x6820, 0xa084, 0x8000, 0x0040, 0x3c18, 0xa6b5, + 0x0400, 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3c26, + 0x681c, 0xa084, 0x8000, 0x00c0, 0x3c26, 0xa6b5, 0x0800, 0x6820, + 0xa084, 0x0100, 0x0040, 0x3c26, 0xa6b5, 0x4000, 0x681c, 0xa084, + 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3c72, 0x2004, 0xa635, + 0xa684, 0x0100, 0x0040, 0x3c40, 0x682c, 0xa084, 0x0001, 0x0040, + 0x3c40, 0x7888, 0xa084, 0x0040, 0x0040, 0x3c40, 0xa6b5, 0x8000, + 0x789b, 0x007e, 0x7eae, 0x6eb6, 0x6814, 0x8007, 0x78aa, 0x7882, + 0x7aaa, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3c6c, 0x0018, 0x3c6c, + 0x70b4, 0xa080, 0x00dd, 0x781a, 0x1078, 0x38de, 0xa684, 0x0200, + 0x0040, 0x3c60, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x45ad, + 0x2d00, 0x70a2, 0x704a, 0x6810, 0x70be, 0x7003, 0x0007, 0xad80, + 0x000f, 0x7036, 0x0078, 0x2438, 0x1078, 0x1b45, 0x1078, 0x38de, + 0x0078, 0x2438, 0x0000, 0x0300, 0x0200, 0x0000, 0x1078, 0x23ca, + 0x2300, 0x0079, 0x3c7b, 0x3c7e, 0x3c7e, 0x3c80, 0x1078, 0x23ca, + 0x1078, 0x45bc, 0x6924, 0xa184, 0x00ff, 0xa086, 0x000a, 0x0040, + 0x3c92, 0xa184, 0xff00, 0xa085, 0x000a, 0x6826, 0x1078, 0x1b45, + 0x0078, 0x3b60, 0x2001, 0x000a, 0x1078, 0x454c, 0x0078, 0x3b60, + 0xa282, 0x0005, 0x0050, 0x3c9e, 0x1078, 0x23ca, 0x7000, 0xa084, + 0x0007, 0x10c0, 0x398a, 0x1078, 0x191a, 0x00c0, 0x3cbd, 0xa684, + 0x0004, 0x0040, 0x3caf, 0x2001, 0x2800, 0x0078, 0x3cb1, 0x2001, + 0x0800, 0x71b4, 0xa188, 0x0091, 0x789b, 0x000e, 0x78aa, 0x2031, + 0x0400, 0x7e5a, 0x791a, 0x0078, 0x2438, 0x6807, 0x0106, 0x680b, + 0x0000, 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0, + 0x3cde, 0xa286, 0x0002, 0x00c0, 0x3cde, 0x78a0, 0xa005, 0x00c0, + 0x3cde, 0xa484, 0x8000, 0x00c0, 0x3cde, 0x78e4, 0xa084, 0x0008, + 0x0040, 0x3cde, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x40d3, + 0x2d00, 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824, + 0xa084, 0x0080, 0x0040, 0x3cf0, 0x1078, 0x4180, 0x0078, 0x2438, + 0x2300, 0x0079, 0x3cf3, 0x3cf6, 0x3d77, 0x3d96, 0x2200, 0x0079, + 0x3cf9, 0x3cfe, 0x3d0e, 0x3d34, 0x3d40, 0x3d63, 0x2029, 0x0001, + 0xa026, 0x2011, 0x0000, 0x1078, 0x428d, 0x0079, 0x3d07, 0x3d0c, + 0x2438, 0x3b60, 0x3d0c, 0x3d0c, 0x1078, 0x23ca, 0x7990, 0xa18c, + 0x0007, 0x00c0, 0x3d15, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684, + 0x0004, 0x0040, 0x3d1d, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011, + 0x0001, 0x1078, 0x428d, 0x0079, 0x3d25, 0x3d2a, 0x2438, 0x3b60, + 0x3d32, 0x3d2c, 0x0078, 0x45ea, 0x70ab, 0x3d30, 0x0078, 0x2438, + 0x0078, 0x3d2a, 0x1078, 0x23ca, 0xa684, 0x0010, 0x0040, 0x3d3e, + 0x1078, 0x414f, 0x0040, 0x3d3e, 0x0078, 0x2438, 0x0078, 0x41bc, + 0x6000, 0xa084, 0x0002, 0x0040, 0x3d5d, 0x70b4, 0xa080, 0x00cd, + 0x781a, 0x0d7e, 0x1078, 0x45c5, 0x2d00, 0x682e, 0x6827, 0x0000, + 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x193d, 0x7003, 0x0000, 0x7037, + 0x0000, 0x704b, 0x0000, 0x0078, 0x3b60, 0xa684, 0x0004, 0x00c0, + 0x3d63, 0x0078, 0x45ea, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3d75, + 0x6000, 0xa084, 0x0001, 0x0040, 0x3d75, 0x70ab, 0x3d75, 0x2001, + 0x0007, 0x1078, 0x4544, 0x0078, 0x45f0, 0x0078, 0x45ea, 0x2200, + 0x0079, 0x3d7a, 0x3d7f, 0x3d7f, 0x3d7f, 0x3d81, 0x3d7f, 0x1078, + 0x23ca, 0x70a7, 0x3d85, 0x0078, 0x45f6, 0x2011, 0x0018, 0x1078, + 0x4287, 0x0079, 0x3d8b, 0x3d90, 0x2438, 0x3b60, 0x3d92, 0x3d94, + 0x1078, 0x23ca, 0x1078, 0x23ca, 0x1078, 0x23ca, 0x2200, 0x0079, + 0x3d99, 0x3d9e, 0x3da0, 0x3da0, 0x3d9e, 0x3d9e, 0x1078, 0x23ca, + 0x78e4, 0xa084, 0x0008, 0x0040, 0x3db5, 0x70a7, 0x3da9, 0x0078, + 0x45f6, 0x2011, 0x0004, 0x1078, 0x4287, 0x0079, 0x3daf, 0x3db5, + 0x2438, 0x3b60, 0x3db5, 0x3dbf, 0x3dc3, 0x70ab, 0x3dbd, 0x2001, + 0x0003, 0x1078, 0x4544, 0x0078, 0x45f0, 0x0078, 0x45ea, 0x70ab, + 0x3db5, 0x0078, 0x2438, 0x70ab, 0x3dc7, 0x0078, 0x2438, 0x0078, + 0x3dbd, 0xa282, 0x0003, 0x0050, 0x3dcf, 0x1078, 0x23ca, 0xa386, + 0x0002, 0x00c0, 0x3de8, 0xa286, 0x0002, 0x00c0, 0x3dee, 0x78a0, + 0xa005, 0x00c0, 0x3dee, 0xa484, 0x8000, 0x00c0, 0x3dee, 0x78e4, + 0xa084, 0x0008, 0x0040, 0x3de8, 0xa6b5, 0x0008, 0x2019, 0x0000, + 0xa684, 0x0008, 0x0040, 0x3dee, 0x1078, 0x412c, 0x6810, 0x70be, + 0x7003, 0x0007, 0x2300, 0x0079, 0x3df5, 0x3df8, 0x3e25, 0x3e2d, + 0x2200, 0x0079, 0x3dfb, 0x3e00, 0x3dfe, 0x3e19, 0x1078, 0x23ca, + 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078, 0x428d, + 0x0079, 0x3e0a, 0x3e0f, 0x2438, 0x3b60, 0x3e17, 0x3e11, 0x0078, + 0x45ea, 0x70ab, 0x3e15, 0x0078, 0x2438, 0x0078, 0x3e0f, 0x1078, + 0x23ca, 0xa684, 0x0010, 0x0040, 0x3e23, 0x1078, 0x414f, 0x0040, + 0x3e23, 0x0078, 0x2438, 0x0078, 0x41bc, 0x2200, 0x0079, 0x3e28, + 0x3e2b, 0x3e2b, 0x3e2b, 0x1078, 0x23ca, 0x2200, 0x0079, 0x3e30, + 0x3e33, 0x3e35, 0x3e35, 0x1078, 0x23ca, 0x78e4, 0xa084, 0x0008, + 0x0040, 0x3e4a, 0x70a7, 0x3e3e, 0x0078, 0x45f6, 0x2011, 0x0004, + 0x1078, 0x4287, 0x0079, 0x3e44, 0x3e4a, 0x2438, 0x3b60, 0x3e4a, + 0x3e54, 0x3e58, 0x70ab, 0x3e52, 0x2001, 0x0003, 0x1078, 0x4544, + 0x0078, 0x45f0, 0x0078, 0x45ea, 0x70ab, 0x3e4a, 0x0078, 0x2438, + 0x70ab, 0x3e5c, 0x0078, 0x2438, 0x0078, 0x3e52, 0x2300, 0x0079, + 0x3e61, 0x3e66, 0x3e68, 0x3e64, 0x1078, 0x23ca, 0x70a4, 0x007a, + 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3e70, 0x1078, 0x23ca, + 0xa684, 0x0200, 0x0040, 0x3e7a, 0x1078, 0x45b5, 0x1078, 0x426f, + 0x1078, 0x45bc, 0x2300, 0x0079, 0x3e7d, 0x3e80, 0x3ea4, 0x3f0a, + 0xa286, 0x0001, 0x0040, 0x3e86, 0x1078, 0x23ca, 0xa684, 0x0200, + 0x0040, 0x3e8e, 0x1078, 0x45b5, 0x1078, 0x45bc, 0x2001, 0x0001, + 0x1078, 0x454c, 0x78b8, 0xa084, 0xc001, 0x0040, 0x3ea0, 0x7848, + 0xa085, 0x0008, 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3e9b, + 0x7003, 0x0000, 0x0078, 0x3b60, 0x2200, 0x0079, 0x3ea7, 0x3ea9, + 0x3eda, 0x70a7, 0x3ead, 0x0078, 0x45f6, 0x2011, 0x000d, 0x1078, + 0x4287, 0x0079, 0x3eb3, 0x3eba, 0x2438, 0x3b60, 0x3ec2, 0x3eca, + 0x3ed0, 0x3ed2, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, + 0x0078, 0x45e4, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, + 0x0078, 0x45e4, 0x70ab, 0x3ece, 0x0078, 0x2438, 0x0078, 0x3eba, + 0x1078, 0x23ca, 0x70ab, 0x3ed6, 0x0078, 0x2438, 0x1078, 0x45fc, + 0x0078, 0x2438, 0x70a7, 0x3ede, 0x0078, 0x45f6, 0x2011, 0x0012, + 0x1078, 0x4287, 0x0079, 0x3ee4, 0x3eea, 0x2438, 0x3b60, 0x3ef6, + 0x3efe, 0x3f04, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, + 0x70b4, 0xa080, 0x00a5, 0x781a, 0x0078, 0x2438, 0xa6b4, 0x00ff, + 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0x70ab, 0x3f02, + 0x0078, 0x2438, 0x0078, 0x3eea, 0x70ab, 0x3f08, 0x0078, 0x2438, + 0x0078, 0x3ef6, 0xa286, 0x0001, 0x0040, 0x3f10, 0x1078, 0x23ca, + 0x70a7, 0x3f14, 0x0078, 0x45f6, 0x2011, 0x0015, 0x1078, 0x4287, + 0x0079, 0x3f1a, 0x3f1f, 0x2438, 0x3b60, 0x3f2d, 0x3f39, 0xa6b4, + 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4, + 0xa080, 0x00b5, 0x781a, 0x0078, 0x2438, 0xa6b4, 0x00ff, 0xa6b5, + 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00a5, 0x781a, 0x0078, + 0x2438, 0x70ab, 0x3f3d, 0x0078, 0x2438, 0x0078, 0x3f1f, 0xa282, + 0x0003, 0x0050, 0x3f45, 0x1078, 0x23ca, 0x2300, 0x0079, 0x3f48, + 0x3f4b, 0x3f82, 0x3fdd, 0xa286, 0x0001, 0x0040, 0x3f51, 0x1078, + 0x23ca, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3f5e, + 0x1078, 0x3ac2, 0x7003, 0x0000, 0x0078, 0x3b60, 0x683b, 0x0000, + 0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x3f6c, 0x1078, 0x45b5, + 0x1078, 0x426f, 0x1078, 0x45bc, 0x2001, 0x0001, 0x1078, 0x454c, + 0x78b8, 0xa084, 0xc001, 0x0040, 0x3f7e, 0x7848, 0xa085, 0x0008, + 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3f79, 0x7003, 0x0000, + 0x0078, 0x3b60, 0x2200, 0x0079, 0x3f85, 0x3f87, 0x3fb8, 0x70a7, + 0x3f8b, 0x0078, 0x45f6, 0x2011, 0x000d, 0x1078, 0x4287, 0x0079, + 0x3f91, 0x3f98, 0x2438, 0x3b60, 0x3fa0, 0x3fa8, 0x3fae, 0x3fb0, + 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, + 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, + 0x70ab, 0x3fac, 0x0078, 0x2438, 0x0078, 0x3f98, 0x1078, 0x23ca, + 0x70ab, 0x3fb4, 0x0078, 0x2438, 0x1078, 0x45fc, 0x0078, 0x2438, + 0x70a7, 0x3fbc, 0x0078, 0x45f6, 0x2011, 0x0005, 0x1078, 0x4287, + 0x0079, 0x3fc2, 0x3fc7, 0x2438, 0x3b60, 0x3fcf, 0x3fd7, 0xa6b4, + 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0xa6b4, + 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0x70ab, + 0x3fdb, 0x0078, 0x2438, 0x0078, 0x3fc7, 0xa286, 0x0001, 0x0040, + 0x3fe3, 0x1078, 0x23ca, 0x70a7, 0x3fe7, 0x0078, 0x45f6, 0x2011, + 0x0006, 0x1078, 0x4287, 0x0079, 0x3fed, 0x3ff2, 0x2438, 0x3b60, + 0x3ff8, 0x4002, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, + 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a, + 0x0078, 0x45e4, 0x70ab, 0x4006, 0x0078, 0x2438, 0x0078, 0x3ff2, + 0x2300, 0x0079, 0x400b, 0x4010, 0x400e, 0x400e, 0x1078, 0x23ca, + 0x1078, 0x23ca, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be, + 0xa282, 0x0003, 0x0050, 0x401e, 0x1078, 0x23ca, 0x2300, 0x0079, + 0x4021, 0x4024, 0x4037, 0x4059, 0x82ff, 0x00c0, 0x4029, 0x1078, + 0x23ca, 0xa684, 0x0200, 0x0040, 0x4031, 0x1078, 0x45b5, 0x1078, + 0x45bc, 0x2001, 0x0001, 0x1078, 0x454c, 0x0078, 0x2438, 0xa296, + 0x0002, 0x0040, 0x4040, 0x82ff, 0x0040, 0x4040, 0x1078, 0x23ca, + 0x70a7, 0x4044, 0x0078, 0x45f6, 0x2011, 0x0018, 0x1078, 0x4287, + 0x0079, 0x404a, 0x404f, 0x2438, 0x3b60, 0x4051, 0x4053, 0x0078, + 0x45e4, 0x0078, 0x45e4, 0x70ab, 0x4057, 0x0078, 0x2438, 0x0078, + 0x404f, 0x2200, 0x0079, 0x405c, 0x405e, 0x4077, 0x70a7, 0x4062, + 0x0078, 0x45f6, 0x2011, 0x0017, 0x1078, 0x4287, 0x0079, 0x4068, + 0x406d, 0x2438, 0x3b60, 0x406f, 0x4071, 0x0078, 0x45e4, 0x0078, + 0x45e4, 0x70ab, 0x4075, 0x0078, 0x2438, 0x0078, 0x406d, 0xa484, + 0x8000, 0x00c0, 0x40c1, 0xa684, 0x0100, 0x0040, 0x408b, 0x1078, + 0x45b5, 0x1078, 0x426f, 0x1078, 0x45bc, 0x7848, 0xa085, 0x000c, + 0x784a, 0x0078, 0x408f, 0x78d8, 0x78d2, 0x78dc, 0x78d6, 0xa6b4, + 0xefff, 0x7e5a, 0x70a7, 0x4096, 0x0078, 0x45f6, 0x2011, 0x000d, + 0x1078, 0x4287, 0x0079, 0x409c, 0x40a3, 0x2438, 0x3b60, 0x40a3, + 0x40b1, 0x40b7, 0x40b9, 0xa684, 0x0100, 0x0040, 0x40af, 0x1078, + 0x4573, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x45ad, 0x0078, + 0x45e4, 0x70ab, 0x40b5, 0x0078, 0x2438, 0x0078, 0x40a3, 0x1078, + 0x23ca, 0x70ab, 0x40bd, 0x0078, 0x2438, 0x1078, 0x45fc, 0x0078, + 0x2438, 0x1078, 0x45bc, 0x70ab, 0x40cb, 0x2001, 0x0003, 0x1078, + 0x4544, 0x0078, 0x45f0, 0x1078, 0x45ad, 0x682c, 0x78d2, 0x6830, + 0x78d6, 0x0078, 0x45e4, 0x70b8, 0x6812, 0x70be, 0x8000, 0x70ba, + 0x681b, 0x0000, 0xa684, 0x0008, 0x0040, 0x40f6, 0x157e, 0x137e, + 0x147e, 0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f, + 0x681a, 0x80ac, 0x789b, 0x0000, 0xaf80, 0x002b, 0x2098, 0xad80, + 0x000b, 0x20a0, 0x53a5, 0x147f, 0x137f, 0x157f, 0xa6c4, 0x0f00, + 0xa684, 0x0002, 0x00c0, 0x4102, 0x692c, 0x810d, 0x810d, 0x810d, + 0x0078, 0x410f, 0x789b, 0x0010, 0x79ac, 0x0078, 0x410f, 0x017e, + 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x457e, 0x017f, 0xa184, + 0x001f, 0xa805, 0x6816, 0x1078, 0x3b33, 0x68be, 0xa684, 0x0004, + 0x0040, 0x4120, 0xa18c, 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105, + 0x682a, 0xa6b4, 0x00ff, 0x6000, 0xa084, 0x0008, 0x0040, 0x412a, + 0xa6b5, 0x4000, 0x6eb6, 0x007c, 0x157e, 0x137e, 0x147e, 0x6918, + 0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f, 0x007e, + 0xa100, 0x681a, 0x007f, 0x8000, 0x8004, 0x0040, 0x414b, 0x20a8, + 0x8104, 0xa080, 0x000b, 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80, + 0x002b, 0x2098, 0x53a5, 0x147f, 0x137f, 0x157f, 0x007c, 0x682c, + 0xa084, 0x0020, 0x00c0, 0x4157, 0x620c, 0x0078, 0x4158, 0x6210, + 0x6b18, 0x2300, 0xa202, 0x0040, 0x4178, 0x2018, 0xa382, 0x000e, + 0x0048, 0x4168, 0x0040, 0x4168, 0x2019, 0x000e, 0x0078, 0x416c, + 0x7858, 0xa084, 0xffef, 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000, + 0x7ba2, 0x70b4, 0xa080, 0x008e, 0x781a, 0xa085, 0x0001, 0x007c, + 0x7858, 0xa084, 0xffef, 0x785a, 0x7893, 0x0000, 0xa006, 0x007c, + 0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x418d, 0xa196, + 0x000f, 0x0040, 0x418d, 0x6807, 0x0117, 0x6914, 0x1078, 0x3b33, + 0x6100, 0x8104, 0x00c8, 0x41a8, 0x601c, 0xa005, 0x0040, 0x419c, + 0x2001, 0x0800, 0x0078, 0x41aa, 0x0d7e, 0x6824, 0x007e, 0x1078, + 0x45c5, 0x007f, 0x6826, 0x2d00, 0x682e, 0x1078, 0x3ac2, 0x0d7f, + 0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, + 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4, + 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684, 0x0002, + 0x00c0, 0x41cf, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x001f, + 0xa805, 0x6816, 0x1078, 0x3b33, 0x68be, 0x0078, 0x41d2, 0x6914, + 0x1078, 0x3b33, 0x6100, 0x8104, 0x00c8, 0x421c, 0xa184, 0x0300, + 0x0040, 0x41de, 0x6807, 0x0117, 0x0078, 0x41fc, 0x6004, 0xa005, + 0x00c0, 0x4205, 0x6807, 0x0117, 0x601c, 0xa005, 0x00c0, 0x41f2, + 0x0d7e, 0x1078, 0x45c5, 0x6827, 0x0034, 0x2d00, 0x682e, 0x1078, + 0x3ac2, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x41fc, 0x2031, 0x0400, + 0x2001, 0x2800, 0x0078, 0x4200, 0x2031, 0x0400, 0x2001, 0x0800, + 0x71b4, 0xa188, 0x0091, 0x0078, 0x424a, 0x6018, 0xa005, 0x00c0, + 0x41f2, 0x601c, 0xa005, 0x00c0, 0x41f2, 0x689f, 0x0000, 0x6827, + 0x003d, 0xa684, 0x0001, 0x0040, 0x4258, 0xa6b5, 0x0800, 0x71b4, + 0xa188, 0x00ae, 0x0078, 0x4253, 0x6807, 0x0117, 0x2031, 0x0400, + 0x692c, 0xa18c, 0x00ff, 0xa186, 0x0012, 0x00c0, 0x422d, 0x2001, + 0x4265, 0x2009, 0x0001, 0x0078, 0x423e, 0xa186, 0x0003, 0x00c0, + 0x4237, 0x2001, 0x4266, 0x2009, 0x0012, 0x0078, 0x423e, 0x2001, + 0x0200, 0x71b4, 0xa188, 0x0091, 0x0078, 0x424a, 0x1078, 0x4598, + 0x78a3, 0x0000, 0x681c, 0xa085, 0x0040, 0x681e, 0x71b4, 0xa188, + 0x00da, 0xa006, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, + 0xa085, 0x8000, 0x6822, 0x6eb6, 0x7e5a, 0x791a, 0x0078, 0x2438, + 0x6eb6, 0x1078, 0x3ac2, 0x6810, 0x70be, 0x7003, 0x0007, 0x70a3, + 0x0000, 0x704b, 0x0000, 0x0078, 0x2438, 0x0023, 0x0070, 0x0005, + 0x0000, 0x0a00, 0x0000, 0x0000, 0x0025, 0x0000, 0x0000, 0x683b, + 0x0000, 0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x4286, 0x78b8, + 0xa08c, 0x001f, 0xa084, 0x8000, 0x0040, 0x427f, 0x8108, 0x78d8, + 0xa100, 0x6836, 0x78dc, 0xa081, 0x0000, 0x683a, 0x007c, 0x7990, + 0x810f, 0xa5ac, 0x0007, 0x2021, 0x0000, 0xa480, 0x0010, 0x789a, + 0x79a8, 0xa18c, 0x00ff, 0xa184, 0x0080, 0x00c0, 0x42b5, 0xa182, + 0x0020, 0x00c8, 0x42cf, 0xa182, 0x0012, 0x00c8, 0x4536, 0x2100, + 0x1079, 0x42a3, 0x007c, 0x4536, 0x447e, 0x4536, 0x4536, 0x42dc, + 0x42df, 0x4319, 0x434f, 0x4381, 0x4384, 0x4536, 0x4536, 0x433a, + 0x43a8, 0x43e2, 0x4536, 0x4536, 0x4409, 0xa18c, 0x001f, 0x6814, + 0xa084, 0x001f, 0xa106, 0x0040, 0x42cc, 0x70b4, 0xa080, 0x00cd, + 0x781a, 0x2001, 0x0014, 0x1078, 0x454c, 0x1078, 0x45bc, 0x7003, + 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000, 0x007c, 0xa182, + 0x0024, 0x00c8, 0x4536, 0xa184, 0x0003, 0x1079, 0x42a3, 0x007c, + 0x4536, 0x4536, 0x4536, 0x4536, 0x1078, 0x4536, 0x007c, 0x2200, + 0x0079, 0x42e2, 0x440c, 0x440c, 0x4306, 0x4306, 0x4306, 0x4306, + 0x4306, 0x4306, 0x4306, 0x4306, 0x4304, 0x4306, 0x42fb, 0x4306, + 0x4306, 0x4306, 0x4306, 0x4306, 0x430e, 0x4311, 0x440c, 0x4311, + 0x4306, 0x4306, 0x4306, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x36b0, + 0x077f, 0x0c7f, 0x0078, 0x4306, 0x1078, 0x44d1, 0x6827, 0x02b3, + 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x4440, 0x1078, 0x452b, + 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, + 0x4428, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x4323, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x45c5, 0x6827, + 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3a92, 0x1078, + 0x4466, 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001, + 0x0002, 0x007c, 0x1078, 0x4466, 0x2001, 0x0017, 0x1078, 0x454c, + 0x70a3, 0x0000, 0x2009, 0x5038, 0x200b, 0x0006, 0x70af, 0x0017, + 0x2009, 0x0200, 0x1078, 0x39d2, 0x2001, 0x0001, 0x007c, 0x2200, + 0x0079, 0x4352, 0x440c, 0x443d, 0x443d, 0x443d, 0x4373, 0x444d, + 0x4379, 0x444d, 0x444d, 0x4450, 0x4450, 0x4455, 0x4455, 0x436b, + 0x436b, 0x443d, 0x443d, 0x444d, 0x443d, 0x4379, 0x440c, 0x4379, + 0x4379, 0x4379, 0x4379, 0x6827, 0x0084, 0x2009, 0x000b, 0x2001, + 0x4300, 0x0078, 0x445f, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078, + 0x4440, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078, + 0x4428, 0x2001, 0x0000, 0x007c, 0x2200, 0x0079, 0x4387, 0x440c, + 0x43a0, 0x43a0, 0x43a0, 0x43a0, 0x444d, 0x444d, 0x444d, 0x444d, + 0x444d, 0x444d, 0x444d, 0x444d, 0x43a0, 0x43a0, 0x43a0, 0x43a0, + 0x444d, 0x43a0, 0x43a0, 0x444d, 0x444d, 0x444d, 0x444d, 0x440c, + 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078, 0x4428, + 0xa684, 0x0004, 0x00c0, 0x43bc, 0x6804, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x00c0, 0x4536, 0x1078, 0x4466, 0x6807, 0x0117, 0x1078, + 0x3ac2, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040, + 0x4536, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x43cb, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x45c5, 0x6827, + 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3aa1, 0x1078, + 0x4466, 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001, + 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040, 0x4536, 0x2d58, + 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006, 0x00c0, 0x43f1, 0x6807, + 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078, 0x45c5, 0x6827, 0x0036, + 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ab1, 0x1078, 0x4466, + 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001, 0x0002, + 0x007c, 0x1078, 0x4536, 0x007c, 0x70b4, 0xa080, 0x00cd, 0x781a, + 0x2001, 0x0001, 0x1078, 0x454c, 0x1078, 0x45bc, 0x7003, 0x0000, + 0x2001, 0x0002, 0x007c, 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078, + 0x426f, 0x1078, 0x4180, 0x1078, 0x45bc, 0x2001, 0x0001, 0x007c, + 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078, 0x426f, 0x70b4, 0xa080, + 0x00cd, 0x781a, 0x2001, 0x0013, 0x1078, 0x454c, 0x1078, 0x45bc, + 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x4536, 0x007c, + 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078, 0x426f, 0x1078, 0x4180, + 0x1078, 0x45bc, 0x2001, 0x0001, 0x007c, 0x2001, 0x0003, 0x007c, + 0x1078, 0x44d1, 0x2001, 0x0000, 0x007c, 0x0c7e, 0x077e, 0x6f14, + 0x1078, 0x36b0, 0x077f, 0x0c7f, 0x2001, 0x0000, 0x007c, 0x1078, + 0x457e, 0x1078, 0x4536, 0x2001, 0x0006, 0x007c, 0x6904, 0xa18c, + 0x00ff, 0xa186, 0x0007, 0x0040, 0x4471, 0xa186, 0x000f, 0x00c0, + 0x4475, 0x1078, 0x45b5, 0x1078, 0x426f, 0x70b4, 0xa080, 0x00cd, + 0x781a, 0x1078, 0x45bc, 0x7003, 0x0000, 0x007c, 0x7aa8, 0xa294, + 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4536, + 0x1079, 0x448b, 0x007c, 0x4536, 0x448f, 0x4536, 0x44df, 0xa282, + 0x0003, 0x0040, 0x4496, 0x1078, 0x4536, 0x007c, 0x7da8, 0xa5ac, + 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0xa482, 0x000c, 0x0048, 0x44a4, + 0x0040, 0x44a4, 0x2021, 0x000c, 0x701c, 0xa502, 0x00c8, 0x44a9, + 0x751c, 0x1078, 0x451c, 0x852b, 0x852b, 0x1078, 0x372e, 0x0040, + 0x44b5, 0x1078, 0x44c3, 0x0078, 0x44b9, 0x1078, 0x4518, 0x1078, + 0x44d1, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, + 0x2001, 0x0004, 0x007c, 0x0c7e, 0x6914, 0x810f, 0xa18c, 0x000f, + 0x810b, 0x810b, 0x810b, 0xa1e0, 0x5280, 0x1078, 0x3538, 0x0c7f, + 0x007c, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, + 0x8003, 0xa0e0, 0x5280, 0x1078, 0x355f, 0x0c7f, 0x007c, 0xa282, + 0x0002, 0x00c0, 0x4536, 0x7aa8, 0xa294, 0x00ff, 0xa284, 0xfffe, + 0x0040, 0x44ec, 0x2011, 0x0001, 0x1078, 0x450a, 0x1078, 0x44fc, + 0x1078, 0x44d1, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, + 0x781a, 0x2001, 0x0004, 0x007c, 0x0c7e, 0x6814, 0x8007, 0xa084, + 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, 0x5280, 0x1078, 0x3604, + 0x0c7f, 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0002, + 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab, 0x0004, 0x007c, + 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001, + 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081, + 0x78ab, 0x0005, 0x007c, 0x2001, 0x0003, 0x1078, 0x4544, 0x70b4, + 0xa080, 0x00b9, 0x781a, 0x2001, 0x0005, 0x007c, 0x2001, 0x0007, + 0x1078, 0x4544, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, + 0x781a, 0x2001, 0x0004, 0x007c, 0x789b, 0x0018, 0x78aa, 0x789b, + 0x0081, 0x78ab, 0x0001, 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa196, + 0x0007, 0x0040, 0x455a, 0xa196, 0x000f, 0x0040, 0x455a, 0x1078, + 0x193d, 0x007c, 0x6924, 0xa194, 0x003f, 0x00c0, 0x4563, 0xa18c, + 0xffc0, 0xa105, 0x6826, 0x1078, 0x3ac2, 0x691c, 0xa184, 0x0100, + 0x0040, 0x4572, 0x1078, 0x1b7e, 0x6914, 0x1078, 0x3b33, 0x6204, + 0x8210, 0x6206, 0x007c, 0x692c, 0x6834, 0x682e, 0xa112, 0x6930, + 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301, 0x007c, 0x0c7e, 0xade0, + 0x0018, 0x6003, 0x0070, 0x6106, 0x600b, 0x0000, 0x600f, 0x0a00, + 0x6013, 0x0000, 0x6017, 0x0000, 0x8007, 0x601a, 0x601f, 0x0000, + 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085, 0x0080, 0x6826, 0x007c, + 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80, 0x002d, 0x20a0, 0x81ac, + 0x0040, 0x45a3, 0x53a6, 0xa184, 0x0001, 0x0040, 0x45a9, 0x3304, + 0x78be, 0x147f, 0x137f, 0x157f, 0x007c, 0x70b0, 0xa005, 0x10c0, + 0x23ca, 0x70b3, 0x8000, 0x0078, 0x48f7, 0x71b0, 0x81ff, 0x0040, + 0x45bb, 0x1078, 0x49ed, 0x007c, 0x71b0, 0x81ff, 0x0040, 0x45c4, + 0x70b3, 0x0000, 0x1078, 0x4633, 0x007c, 0x0c7e, 0x0d7e, 0x1078, + 0x191a, 0x0c7f, 0x157e, 0x137e, 0x147e, 0x2da0, 0x2c98, 0x20a9, + 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f, 0x6807, 0x010d, 0x680b, + 0x0000, 0x7004, 0x8007, 0x681a, 0x6823, 0x0000, 0x681f, 0x0000, + 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4, 0xa080, 0x0091, 0x781a, + 0x0078, 0x2438, 0x70b4, 0xa080, 0x0081, 0x781a, 0x0078, 0x2438, + 0x70b4, 0xa080, 0x00b9, 0x781a, 0x0078, 0x2438, 0x70b4, 0xa080, + 0x00c3, 0x781a, 0x0078, 0x2438, 0x6904, 0xa18c, 0x00ff, 0xa196, + 0x0007, 0x0040, 0x4609, 0xa196, 0x000f, 0x0040, 0x4609, 0x6807, + 0x0117, 0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, + 0x6820, 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a, + 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c, 0x1078, 0x45bc, 0x7848, + 0xa085, 0x000c, 0x784a, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x2009, + 0x000b, 0x2001, 0x4400, 0x1078, 0x457e, 0x2001, 0x0013, 0x1078, + 0x454c, 0x0078, 0x3b60, 0x127e, 0x2091, 0x2200, 0x2049, 0x4633, + 0x7000, 0x7204, 0xa205, 0x720c, 0xa215, 0x7008, 0xa084, 0xfff7, + 0xa205, 0x0040, 0x4645, 0x0078, 0x464a, 0x7003, 0x0000, 0x127f, + 0x2000, 0x007c, 0x7000, 0xa084, 0x0001, 0x00c0, 0x4678, 0x7108, + 0x8103, 0x00c8, 0x4657, 0x1078, 0x477a, 0x0078, 0x464f, 0x700c, + 0xa08c, 0x00ff, 0x0040, 0x4678, 0x7004, 0x8004, 0x00c8, 0x466f, + 0x7014, 0xa005, 0x00c0, 0x466b, 0x7010, 0xa005, 0x0040, 0x466f, + 0xa102, 0x00c8, 0x464f, 0x7007, 0x0010, 0x0078, 0x4678, 0x8aff, + 0x0040, 0x4678, 0x1078, 0x49c4, 0x00c0, 0x4672, 0x0040, 0x464f, + 0x1078, 0x4703, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x017e, + 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x468b, 0xa18e, + 0x000f, 0x00c0, 0x468e, 0x6040, 0x0078, 0x468f, 0x6428, 0x017f, + 0x84ff, 0x0040, 0x46b9, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, + 0x46c9, 0x273c, 0x87fb, 0x00c0, 0x46a7, 0x0048, 0x46a1, 0x1078, + 0x23ca, 0x609c, 0xa075, 0x0040, 0x46b9, 0x0078, 0x4694, 0x2704, + 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0040, 0x46b9, + 0x8738, 0x2704, 0xa005, 0x00c0, 0x46a8, 0x709c, 0xa075, 0x00c0, + 0x4694, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, 0x0015, + 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, + 0x0000, 0x0000, 0x46be, 0x46bb, 0x0000, 0x0000, 0x8000, 0x0000, + 0x46be, 0x0000, 0x46c6, 0x46c3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x46c6, 0x0000, 0x46c1, 0x46c1, 0x0000, 0x0000, 0x8000, 0x0000, + 0x46c1, 0x0000, 0x46c7, 0x46c7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x46c7, 0x127e, 0x2091, 0x2200, 0x2079, 0x5000, 0x2071, 0x0010, + 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2071, 0x0020, + 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2049, 0x0000, + 0x127f, 0x2000, 0x007c, 0x2049, 0x4703, 0x2019, 0x0000, 0x7004, + 0x8004, 0x00c8, 0x4756, 0x7007, 0x0012, 0x7108, 0x7008, 0xa106, + 0x00c0, 0x470d, 0xa184, 0x01e0, 0x0040, 0x4718, 0x1078, 0x23ca, + 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x4723, 0xa184, + 0x4000, 0x00c0, 0x470d, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, + 0x4731, 0xa386, 0x0008, 0x0040, 0x473c, 0xa386, 0x200c, 0x00c0, + 0x470d, 0x7200, 0x8204, 0x0048, 0x473c, 0x730c, 0xa384, 0x00ff, + 0x0040, 0x473c, 0x1078, 0x23ca, 0x7007, 0x0012, 0x7000, 0xa084, + 0x0001, 0x00c0, 0x4756, 0x7008, 0xa084, 0x01e0, 0x00c0, 0x4756, + 0x7310, 0x7014, 0xa305, 0x0040, 0x4756, 0x710c, 0xa184, 0x0300, + 0x00c0, 0x4756, 0xa184, 0x00ff, 0x00c0, 0x4703, 0x7007, 0x0012, + 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x475a, 0x7007, + 0x0012, 0x7108, 0x8103, 0x0048, 0x475f, 0x7003, 0x0000, 0x2049, + 0x0000, 0x007c, 0x107e, 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, + 0x7108, 0x1078, 0x477a, 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, + 0x107f, 0x007c, 0x7204, 0x7500, 0x730c, 0xa384, 0x0300, 0x00c0, + 0x47a1, 0xa184, 0x01e0, 0x00c0, 0x47c5, 0x7108, 0xa184, 0x01e0, + 0x00c0, 0x47c5, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, + 0x4795, 0xa184, 0x4000, 0x00c0, 0x4785, 0xa184, 0x0007, 0x0079, + 0x4799, 0x47a3, 0x47b5, 0x47a1, 0x47b5, 0x47a1, 0x4801, 0x47a1, + 0x47ff, 0x1078, 0x23ca, 0x7004, 0xa084, 0x0010, 0xa085, 0x0002, + 0x7006, 0x8aff, 0x00c0, 0x47b0, 0x2049, 0x0000, 0x0078, 0x47b4, + 0x1078, 0x49c4, 0x00c0, 0x47b0, 0x007c, 0x7004, 0xa084, 0x0010, + 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x47c0, 0x0078, 0x47c4, + 0x1078, 0x49c4, 0x00c0, 0x47c0, 0x007c, 0x7007, 0x0012, 0x7108, + 0x00e0, 0x47c8, 0x2091, 0x6000, 0x00e0, 0x47cc, 0x2091, 0x6000, + 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, + 0x47d4, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048, 0x47d9, 0x7003, + 0x0000, 0x7000, 0xa005, 0x00c0, 0x47ed, 0x7004, 0xa005, 0x00c0, + 0x47ed, 0x700c, 0xa005, 0x0040, 0x47ef, 0x0078, 0x47d0, 0x2049, + 0x0000, 0x1078, 0x37d7, 0x6818, 0xa084, 0x8000, 0x0040, 0x47fa, + 0x681b, 0x0002, 0x007c, 0x1078, 0x23ca, 0x1078, 0x23ca, 0x1078, + 0x485d, 0x7210, 0x7114, 0x700c, 0xa09c, 0x00ff, 0x2800, 0xa300, + 0xa211, 0xa189, 0x0000, 0x1078, 0x485d, 0x2704, 0x2c58, 0xac60, + 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, + 0x0040, 0x4824, 0x00c8, 0x4824, 0x8412, 0x8210, 0x830a, 0xa189, + 0x0000, 0x2b60, 0x0078, 0x480b, 0x2b60, 0x8a07, 0x007e, 0x6004, + 0xa084, 0x0008, 0x0040, 0x4830, 0xa7ba, 0x46c3, 0x0078, 0x4832, + 0xa7ba, 0x46bb, 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, + 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4703, 0x007c, 0x8738, 0x2704, + 0xa005, 0x00c0, 0x4851, 0x609c, 0xa005, 0x0040, 0x485a, 0x2060, + 0x6004, 0xa084, 0x000f, 0xa080, 0x46c9, 0x203c, 0x87fb, 0x1040, + 0x23ca, 0x8a51, 0x0040, 0x4859, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, - 0xa004, 0x00c0, 0x3501, 0x6000, 0xa064, 0x00c0, 0x34f8, 0x2d60, - 0x6004, 0xa084, 0x000f, 0xa080, 0x3356, 0x203c, 0x87fb, 0x1040, - 0x1eac, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6884, + 0xa004, 0x00c0, 0x4871, 0x6000, 0xa064, 0x00c0, 0x4868, 0x2d60, + 0x6004, 0xa084, 0x000f, 0xa080, 0x46d9, 0x203c, 0x87fb, 0x1040, + 0x23ca, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, - 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x351c, - 0xa0b8, 0x3340, 0x0078, 0x351e, 0xa0b8, 0x3338, 0x7e08, 0xa6b5, - 0x000c, 0x681c, 0xa084, 0x0040, 0x0040, 0x3528, 0xa6b5, 0x0001, - 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x352a, 0x2400, - 0xa305, 0x00c0, 0x3535, 0x0078, 0x3559, 0x2c58, 0x2704, 0x6104, - 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, - 0x0008, 0x0040, 0x3549, 0x6010, 0xa001, 0x7022, 0x6014, 0xa001, - 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203, - 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x34ca, 0x0078, - 0x355b, 0x1078, 0x3606, 0x00c0, 0x3559, 0x127f, 0x2000, 0x007c, - 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, - 0xa084, 0x0004, 0x00c0, 0x3567, 0x7003, 0x0008, 0x127f, 0x2000, - 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x3571, - 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x357a, 0x7e08, - 0xa6b5, 0x000c, 0x681c, 0xa084, 0x0020, 0x00c0, 0x3589, 0xa6b5, - 0x0001, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, - 0x3346, 0x273c, 0x87fb, 0x00c0, 0x359f, 0x0048, 0x3599, 0x1078, - 0x1eac, 0x689c, 0xa065, 0x0040, 0x35a3, 0x0078, 0x358c, 0x1078, - 0x3606, 0x00c0, 0x359f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, - 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, - 0xa6b5, 0x000c, 0x681c, 0xa084, 0x0040, 0x0040, 0x35b9, 0xa6b5, - 0x0001, 0x2049, 0x35a6, 0x6828, 0xa055, 0x0040, 0x3603, 0x2d70, - 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3346, 0x273c, 0x87fb, - 0x00c0, 0x35d5, 0x0048, 0x35ce, 0x1078, 0x1eac, 0x709c, 0xa075, - 0x2060, 0x0040, 0x3603, 0x0078, 0x35c1, 0x2704, 0xae68, 0x6808, - 0xa422, 0x680c, 0xa31b, 0x0048, 0x35f0, 0x8a51, 0x00c0, 0x35e2, - 0x1078, 0x1eac, 0x8738, 0x2704, 0xa005, 0x00c0, 0x35d6, 0x709c, - 0xa075, 0x2060, 0x0040, 0x3603, 0x2039, 0x3338, 0x0078, 0x35c1, - 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, - 0x690c, 0x2300, 0xa11b, 0x00c8, 0x35ff, 0x1078, 0x1eac, 0x2071, - 0x0020, 0x0078, 0x3528, 0x127f, 0x2000, 0x007c, 0x7008, 0x7508, - 0xa52e, 0x00c0, 0x3606, 0xa084, 0x0003, 0xa086, 0x0003, 0x0040, - 0x362e, 0x2704, 0xac08, 0x2104, 0x701a, 0x8108, 0x2104, 0x701e, - 0x8108, 0x2104, 0x7012, 0x8108, 0x2104, 0x7016, 0x6004, 0xa084, - 0x0008, 0x0040, 0x3629, 0x8108, 0x2104, 0x7022, 0x8108, 0x2104, - 0x7026, 0x7602, 0x7007, 0x0001, 0x1078, 0x34ca, 0x007c, 0x127e, - 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x362f, 0x0d7f, 0x087f, - 0x7108, 0x7008, 0xa106, 0x00c0, 0x3638, 0xa184, 0x4000, 0x00c0, - 0x3638, 0xa184, 0x0003, 0x00c0, 0x364f, 0x6828, 0xa005, 0x0040, - 0x365d, 0x0020, 0x364f, 0x1078, 0x348f, 0x0078, 0x365d, 0x00a0, - 0x3656, 0x7108, 0x1078, 0x33e7, 0x0078, 0x3638, 0x7007, 0x0010, - 0x00a0, 0x3658, 0x7108, 0x1078, 0x33e7, 0x7008, 0xa086, 0x0008, - 0x00c0, 0x3638, 0x7000, 0xa005, 0x00c0, 0x3638, 0x2049, 0x0000, - 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0d7e, - 0x2091, 0x2200, 0x0d7f, 0x2049, 0x366b, 0xad80, 0x0011, 0x20a0, - 0x2099, 0x0031, 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, - 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x3689, 0x8000, 0x80ac, - 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x368b, - 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, - 0x2000, 0x007c, 0x2091, 0x6000, 0x78c0, 0xa005, 0x0040, 0x36af, - 0x798c, 0x70d0, 0xa106, 0x00c0, 0x36af, 0x7804, 0xa005, 0x0040, - 0x36af, 0x7807, 0x0000, 0x0068, 0x36af, 0x2091, 0x4080, 0x7820, - 0x8001, 0x7822, 0x00c0, 0x370f, 0x7824, 0x7822, 0x2091, 0x8000, - 0x78f0, 0xa005, 0x0040, 0x36dc, 0x78d4, 0xa005, 0x00c0, 0x36dc, - 0x3a10, 0xa284, 0x0002, 0x00c0, 0x36cc, 0x78d7, 0x0007, 0x2009, - 0xff01, 0x200a, 0x0078, 0x36dc, 0xa284, 0x0001, 0x00c0, 0x36d4, - 0x78ef, 0x0000, 0x0078, 0x36dc, 0x78ec, 0xa005, 0x00c0, 0x36dc, - 0x78d7, 0x0008, 0x78ef, 0x0001, 0x2069, 0x3940, 0x6800, 0xa084, - 0x0007, 0x0040, 0x36f3, 0xa086, 0x0002, 0x0040, 0x36f3, 0x6830, - 0xa00d, 0x0040, 0x36f3, 0x2104, 0xa005, 0x0040, 0x36f3, 0x8001, - 0x200a, 0x0040, 0x37b1, 0x7848, 0xa005, 0x0040, 0x3703, 0x8001, - 0x784a, 0x00c0, 0x3703, 0x0f7e, 0x2079, 0x0100, 0x1078, 0x316a, - 0x0f7f, 0x1078, 0x1cf6, 0x68c4, 0xa005, 0x0040, 0x370f, 0x8001, - 0x68c6, 0x00c0, 0x370f, 0x68a3, 0x0000, 0x68a7, 0x0001, 0x1078, - 0x3716, 0x1078, 0x373b, 0x2091, 0x8001, 0x007c, 0x7834, 0x8001, - 0x7836, 0x00c0, 0x373a, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, - 0xa005, 0x00c0, 0x3725, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, - 0x4280, 0x2040, 0x2004, 0xa065, 0x0040, 0x373a, 0x6024, 0xa005, - 0x0040, 0x3736, 0x8001, 0x6026, 0x0040, 0x376a, 0x6000, 0x2c40, - 0x0078, 0x372b, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x3769, - 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x3748, 0x2001, 0x0080, - 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3a80, - 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x3769, 0xa290, - 0x0009, 0x2204, 0xa005, 0x0040, 0x3761, 0x8001, 0x2012, 0x00c0, - 0x3769, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, - 0x1cf6, 0x007c, 0x2069, 0x3940, 0x6800, 0xa005, 0x0040, 0x3774, - 0x683c, 0xac06, 0x0040, 0x37b1, 0x601b, 0x0006, 0x60b4, 0xa084, - 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, - 0x6000, 0x2042, 0x6714, 0x6fb6, 0x1078, 0x18b4, 0x6818, 0xa005, - 0x0040, 0x378c, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, - 0x6810, 0x8001, 0x00d0, 0x3796, 0x1078, 0x1eac, 0x6812, 0x602f, - 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x1a26, 0x2069, 0x3940, - 0x2001, 0x0006, 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x37ac, - 0x69ba, 0x2001, 0x0004, 0x68a2, 0x1078, 0x1cf1, 0x2091, 0x8001, - 0x007c, 0x2009, 0x394f, 0x2164, 0x2069, 0x0100, 0x1078, 0x1e57, - 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, - 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, - 0x6830, 0xa084, 0x0040, 0x0040, 0x37ed, 0x684b, 0x0004, 0x20a9, - 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x37da, 0x0070, 0x37da, - 0x0078, 0x37d1, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, - 0x0001, 0x0040, 0x37e7, 0x0070, 0x37e7, 0x0078, 0x37de, 0x20a9, - 0x00fa, 0x0070, 0x37ed, 0x0078, 0x37e9, 0x6808, 0xa084, 0xfffd, - 0x680a, 0x681b, 0x0047, 0x2009, 0x3968, 0x200b, 0x0007, 0x784c, - 0x784a, 0x2091, 0x8001, 0x007c, 0x2079, 0x3900, 0x1078, 0x3827, - 0x1078, 0x380b, 0x1078, 0x3819, 0x7833, 0x0000, 0x7847, 0x0000, - 0x784b, 0x0000, 0x007c, 0x2019, 0x000c, 0x2011, 0x3946, 0x2204, - 0xa086, 0x003c, 0x0040, 0x3816, 0x2019, 0x0008, 0x7b2a, 0x7b2e, - 0x007c, 0x2019, 0x0039, 0x2011, 0x3946, 0x2204, 0xa086, 0x003c, - 0x0040, 0x3824, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, - 0x3971, 0x2011, 0x3946, 0x2204, 0xa086, 0x003c, 0x0040, 0x3832, - 0x2019, 0x2626, 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, - 0x007c, 0x8e59 + 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x488c, + 0xa0b8, 0x46c3, 0x0078, 0x488e, 0xa0b8, 0x46bb, 0x7e08, 0xa6b5, + 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x489c, + 0xa18e, 0x000f, 0x00c0, 0x48a5, 0x681c, 0xa084, 0x0040, 0x0040, + 0x48ac, 0xa6b5, 0x0001, 0x0078, 0x48ac, 0x681c, 0xa084, 0x0040, + 0x0040, 0x48ac, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084, + 0x0004, 0x00c0, 0x48ae, 0x2400, 0xa305, 0x00c0, 0x48b9, 0x0078, + 0x48df, 0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, + 0x6004, 0xa301, 0x701e, 0xa184, 0x0008, 0x0040, 0x48cf, 0x6010, + 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, + 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, + 0x7007, 0x0001, 0x2b60, 0x1078, 0x483e, 0x0078, 0x48e1, 0x1078, + 0x49c4, 0x00c0, 0x48df, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, + 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, + 0x00c0, 0x48ed, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, + 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x48f7, 0x7007, 0x0004, + 0x7004, 0xa084, 0x0004, 0x00c0, 0x4900, 0x7e08, 0xa6b5, 0x000c, + 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4913, 0xa18e, + 0x000f, 0x00c0, 0x491e, 0x681c, 0xa084, 0x0040, 0x0040, 0x491a, + 0xa6b5, 0x0001, 0x6840, 0x2050, 0x0078, 0x4927, 0x681c, 0xa084, + 0x0020, 0x00c0, 0x4925, 0xa6b5, 0x0001, 0x6828, 0x2050, 0x2d60, + 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x46c9, 0x273c, 0x87fb, 0x00c0, + 0x493b, 0x0048, 0x4935, 0x1078, 0x23ca, 0x689c, 0xa065, 0x0040, + 0x493f, 0x0078, 0x4928, 0x1078, 0x49c4, 0x00c0, 0x493b, 0x127f, + 0x2000, 0x007c, 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, + 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, + 0x00ff, 0xa186, 0x0007, 0x0040, 0x4959, 0xa18e, 0x000f, 0x00c0, + 0x4962, 0x681c, 0xa084, 0x0040, 0x0040, 0x4969, 0xa6b5, 0x0001, + 0x0078, 0x4969, 0x681c, 0xa084, 0x0040, 0x0040, 0x4969, 0xa6b5, + 0x0001, 0x2049, 0x4942, 0x017e, 0x6904, 0xa18c, 0x00ff, 0xa186, + 0x0007, 0x0040, 0x4977, 0xa18e, 0x000f, 0x00c0, 0x497a, 0x6840, + 0x0078, 0x497b, 0x6828, 0x017f, 0xa055, 0x0040, 0x49c1, 0x2d70, + 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x46c9, 0x273c, 0x87fb, + 0x00c0, 0x4995, 0x0048, 0x498e, 0x1078, 0x23ca, 0x709c, 0xa075, + 0x2060, 0x0040, 0x49c1, 0x0078, 0x4981, 0x2704, 0xae68, 0x6808, + 0xa422, 0x680c, 0xa31b, 0x0048, 0x49ae, 0x8a51, 0x00c0, 0x49a2, + 0x1078, 0x23ca, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4996, 0x709c, + 0xa075, 0x2060, 0x0040, 0x49c1, 0x0078, 0x4981, 0x8422, 0x8420, + 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, + 0xa11b, 0x00c8, 0x49bd, 0x1078, 0x23ca, 0x2071, 0x0020, 0x0078, + 0x48ac, 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x0003, 0xa086, + 0x0003, 0x0040, 0x49ec, 0x2704, 0xac08, 0x2104, 0x701a, 0x8108, + 0x2104, 0x701e, 0x8108, 0x2104, 0x7012, 0x8108, 0x2104, 0x7016, + 0x6004, 0xa084, 0x0008, 0x0040, 0x49e3, 0x8108, 0x2104, 0x7022, + 0x8108, 0x2104, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xa085, + 0x0001, 0x7006, 0x1078, 0x483e, 0x007c, 0x127e, 0x007e, 0x0d7e, + 0x2091, 0x2200, 0x2049, 0x49ed, 0x0d7f, 0x087f, 0x7108, 0xa184, + 0x0003, 0x00c0, 0x4a17, 0x017e, 0x6904, 0xa18c, 0x00ff, 0xa186, + 0x0007, 0x0040, 0x4a07, 0xa18e, 0x000f, 0x00c0, 0x4a0a, 0x6840, + 0x0078, 0x4a0b, 0x6828, 0x017f, 0xa005, 0x0040, 0x4a25, 0x0078, + 0x464a, 0x0020, 0x4a17, 0x1078, 0x4801, 0x0078, 0x4a25, 0x00a0, + 0x4a1e, 0x7108, 0x1078, 0x477a, 0x0078, 0x49f6, 0x7007, 0x0010, + 0x00a0, 0x4a20, 0x7108, 0x1078, 0x477a, 0x7008, 0xa086, 0x0008, + 0x00c0, 0x49f6, 0x7000, 0xa005, 0x00c0, 0x49f6, 0x7003, 0x0000, + 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, + 0x157e, 0x0c7e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x4a35, + 0xad80, 0x0011, 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x00ff, + 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, + 0x4a54, 0x8000, 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, + 0x0004, 0x00c0, 0x4a56, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, + 0x157f, 0x137f, 0x147f, 0x127f, 0x2000, 0x007c, 0x2091, 0x6000, + 0x2091, 0x8000, 0x78cc, 0xa005, 0x0040, 0x4a7d, 0x7994, 0x70d0, + 0xa106, 0x00c0, 0x4a7d, 0x7804, 0xa005, 0x0040, 0x4a7d, 0x7807, + 0x0000, 0x0068, 0x4a7d, 0x2091, 0x4080, 0x7820, 0x8001, 0x7822, + 0x00c0, 0x4ad8, 0x7824, 0x7822, 0x2069, 0x5040, 0x6800, 0xa084, + 0x0007, 0x0040, 0x4a9b, 0xa086, 0x0002, 0x0040, 0x4a9b, 0x6834, + 0xa00d, 0x0040, 0x4a9b, 0x2104, 0xa005, 0x0040, 0x4a9b, 0x8001, + 0x200a, 0x0040, 0x4b80, 0x7848, 0xa005, 0x0040, 0x4aa9, 0x8001, + 0x784a, 0x00c0, 0x4aa9, 0x2009, 0x0102, 0x6844, 0x200a, 0x1078, + 0x21b1, 0x6890, 0xa005, 0x0040, 0x4ab5, 0x8001, 0x6892, 0x00c0, + 0x4ab5, 0x686f, 0x0000, 0x6873, 0x0001, 0x2061, 0x5300, 0x20a9, + 0x0100, 0x2009, 0x0002, 0x6034, 0xa005, 0x0040, 0x4acb, 0x8001, + 0x6036, 0x00c0, 0x4acb, 0x6010, 0xa005, 0x0040, 0x4acb, 0x017e, + 0x1078, 0x21b1, 0x017f, 0xace0, 0x0010, 0x0070, 0x4ad1, 0x0078, + 0x4abb, 0x8109, 0x0040, 0x4ad8, 0x20a9, 0x0100, 0x0078, 0x4abb, + 0x1078, 0x4ae5, 0x1078, 0x4b0a, 0x2009, 0x5051, 0x2104, 0x2009, + 0x0102, 0x200a, 0x2091, 0x8001, 0x007c, 0x7834, 0x8001, 0x7836, + 0x00c0, 0x4b09, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, + 0x00c0, 0x4af4, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x7300, + 0x2040, 0x2004, 0xa065, 0x0040, 0x4b09, 0x6024, 0xa005, 0x0040, + 0x4b05, 0x8001, 0x6026, 0x0040, 0x4b39, 0x6000, 0x2c40, 0x0078, + 0x4afa, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x4b38, 0x782c, + 0x782a, 0x7830, 0xa005, 0x00c0, 0x4b17, 0x2001, 0x0200, 0x8001, + 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x5300, 0xa298, + 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x4b38, 0xa290, 0x0009, + 0x2204, 0xa005, 0x0040, 0x4b30, 0x8001, 0x2012, 0x00c0, 0x4b38, + 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x21b1, + 0x007c, 0x2069, 0x5040, 0x6800, 0xa005, 0x0040, 0x4b43, 0x6848, + 0xac06, 0x0040, 0x4b80, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00, + 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, + 0x2042, 0x6714, 0x6f82, 0x1078, 0x1956, 0x6818, 0xa005, 0x0040, + 0x4b5b, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, 0x6810, + 0x8001, 0x00d0, 0x4b65, 0x1078, 0x23ca, 0x6812, 0x602f, 0x0000, + 0x6033, 0x0000, 0x2c68, 0x1078, 0x1c53, 0x2069, 0x5040, 0x7944, + 0xa184, 0x0100, 0x2001, 0x0006, 0x686e, 0x00c0, 0x4b7b, 0x6986, + 0x2001, 0x0004, 0x686e, 0x1078, 0x21ac, 0x2091, 0x8001, 0x007c, + 0x2069, 0x0100, 0x2009, 0x5040, 0x2104, 0xa084, 0x0007, 0x0040, + 0x4bdc, 0xa086, 0x0007, 0x00c0, 0x4b96, 0x0d7e, 0x2009, 0x5052, + 0x216c, 0x1078, 0x3a1a, 0x0d7f, 0x0078, 0x4bdc, 0x2009, 0x5052, + 0x2164, 0x1078, 0x2375, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, + 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, + 0x0000, 0x6033, 0x0000, 0x6830, 0xa084, 0x0040, 0x0040, 0x4bd0, + 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, + 0x4bbd, 0x0070, 0x4bbd, 0x0078, 0x4bb4, 0x684b, 0x0009, 0x20a9, + 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x4bca, 0x0070, 0x4bca, + 0x0078, 0x4bc1, 0x20a9, 0x00fa, 0x0070, 0x4bd0, 0x0078, 0x4bcc, + 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2009, 0x505b, + 0x200b, 0x0007, 0x784c, 0x784a, 0x2091, 0x8001, 0x007c, 0x2079, + 0x5000, 0x1078, 0x4c0a, 0x1078, 0x4bee, 0x1078, 0x4bfc, 0x7833, + 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x007c, 0x2019, 0x0003, + 0x2011, 0x5046, 0x2204, 0xa086, 0x003c, 0x0040, 0x4bf9, 0x2019, + 0x0002, 0x7b2a, 0x7b2e, 0x007c, 0x2019, 0x0039, 0x2011, 0x5046, + 0x2204, 0xa086, 0x003c, 0x0040, 0x4c07, 0x2019, 0x0027, 0x7b36, + 0x7b3a, 0x007c, 0x2019, 0x3971, 0x2011, 0x5046, 0x2204, 0xa086, + 0x003c, 0x0040, 0x4c15, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x783f, + 0x0000, 0x7843, 0x000a, 0x007c, 0x0020, 0x002b, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0014, + 0x0014, 0x9849, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0080, 0x000f, 0x0000, 0x0201, 0x0604, 0x0c08, 0x2120, + 0x4022, 0xf880, 0x0018, 0x300b, 0xa201, 0x0014, 0xa200, 0x0014, + 0xa200, 0x0214, 0x0000, 0x006c, 0x0002, 0x0014, 0x98d5, 0x009e, + 0x009b, 0xa202, 0x8838, 0x3806, 0x8839, 0x20c3, 0x0864, 0x9889, + 0x28c1, 0x9cb6, 0xa203, 0x300c, 0x2846, 0x8161, 0x846a, 0x8300, + 0x1856, 0x883a, 0x9865, 0x28f2, 0x9c95, 0x9858, 0x300c, 0x28e1, + 0x9c95, 0x2809, 0xa206, 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, + 0x782c, 0x786d, 0x9879, 0x282b, 0xa207, 0x64a0, 0x67a0, 0x6fc0, + 0x1814, 0x883b, 0x7822, 0x883e, 0x987d, 0x8576, 0x8677, 0x206b, + 0x28c1, 0x9cb6, 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209, + 0x2901, 0x9891, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c, + 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c95, 0x0014, 0xa204, + 0xa300, 0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e, + 0x87a9, 0x883f, 0x08e6, 0x9895, 0xf881, 0x9890, 0xc801, 0x0014, + 0xf8c1, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, + 0x8532, 0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, + 0xa208, 0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, + 0xf041, 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, + 0x8822, 0x0016, 0x8000, 0x2847, 0x1011, 0x98c8, 0x8000, 0xa000, + 0x2802, 0x1011, 0x98ce, 0x9865, 0x283e, 0x1011, 0x98d2, 0xa20b, + 0x0017, 0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0x98df, + 0x0014, 0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, + 0x3806, 0x0210, 0x9cbb, 0x0704, 0x0000, 0x006c, 0x0002, 0x984f, + 0x0014, 0x009e, 0x00a0, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, + 0x9cd0, 0x8772, 0x8837, 0x2101, 0x987a, 0x10d2, 0x78e2, 0x9cd3, + 0x9859, 0xd984, 0xf0e2, 0xf0a1, 0x98cd, 0x0014, 0x8831, 0xd166, + 0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820, 0x987a, 0x2301, + 0x987a, 0x10d2, 0x78e4, 0x9cd3, 0x8821, 0x8820, 0x9859, 0xf123, + 0xf142, 0xf101, 0x98c6, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, + 0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b, 0x9cd0, 0x2001, + 0x98c5, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0x988d, + 0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9cbc, + 0x6b2a, 0x6902, 0x1834, 0x989d, 0x1814, 0x8010, 0x8592, 0x8026, + 0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9ca9, 0x694b, 0xa213, + 0x1462, 0xa213, 0x8000, 0x16e1, 0x98b5, 0x8023, 0x16e1, 0x8001, + 0x10f1, 0x0016, 0x6969, 0xa214, 0x61c2, 0x8002, 0x14e1, 0x8004, + 0x16e1, 0x0101, 0x300a, 0x8827, 0x0014, 0xa217, 0x9cbc, 0x0014, + 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, + 0x9cd0, 0x10d2, 0x70e4, 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9cd3, + 0x98c5, 0x8827, 0x300a, 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, + 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, + 0x9891, 0xa210, 0xa000, 0x8010, 0x8592, 0x853b, 0xd044, 0x8022, + 0x3807, 0x84bb, 0x98ea, 0x8021, 0x3807, 0x84b9, 0x300c, 0x817e, + 0x872b, 0x8772, 0x9891, 0x0000, 0x0020, 0x002b, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0014, + 0x0014, 0x9849, 0x0014, 0x0014, 0x98ea, 0x98d5, 0x0014, 0x0014, + 0x0014, 0x0080, 0x013f, 0x0000, 0x0201, 0x0604, 0x0c08, 0x2120, + 0x4022, 0xf880, 0x0018, 0x300b, 0xa201, 0x0014, 0xa200, 0x0014, + 0xa200, 0x0214, 0xa202, 0x8838, 0x3806, 0x8839, 0x20c3, 0x0864, + 0xa833, 0x28c1, 0x9cb6, 0xa203, 0x300c, 0x2846, 0x8161, 0x846a, + 0x8300, 0x1856, 0x883a, 0xa804, 0x28f2, 0x9c95, 0xa8f4, 0x300c, + 0x28e1, 0x9c95, 0x2809, 0xa206, 0x64c0, 0x67a0, 0x6fc0, 0x1814, + 0x883b, 0x782c, 0x786d, 0xa808, 0x282b, 0xa207, 0x64a0, 0x67a0, + 0x6fc0, 0x1814, 0x883b, 0x7822, 0x883e, 0xa802, 0x8576, 0x8677, + 0x206b, 0x28c1, 0x9cb6, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e0, + 0xa209, 0x2901, 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, + 0x883c, 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c95, 0x0014, + 0xa204, 0xa300, 0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, + 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f3, 0xf881, 0xa8ec, 0xc801, + 0x0014, 0xf8c1, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, + 0x0014, 0x8532, 0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, + 0x0014, 0xa208, 0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, + 0x842a, 0xf041, 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, + 0x20d5, 0x8822, 0x0016, 0x8000, 0x2847, 0x1011, 0xa8fc, 0x8000, + 0xa000, 0x2802, 0x1011, 0xa8fd, 0xa893, 0x283e, 0x1011, 0xa8fd, + 0xa20b, 0x0017, 0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, + 0xa801, 0x0014, 0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, + 0xa20d, 0x3806, 0x0210, 0x9cbb, 0x0704, 0x0017, 0x60ff, 0x300c, + 0x8720, 0xa211, 0x9d6b, 0x8772, 0x8837, 0x2101, 0xa821, 0x10d2, + 0x78e2, 0x9d6e, 0xa8fc, 0xd984, 0xf0e2, 0xf0a1, 0xa86c, 0x0014, + 0x8831, 0xd166, 0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820, + 0xa80f, 0x2301, 0xa80d, 0x10d2, 0x78e4, 0x9d6e, 0x8821, 0x8820, + 0xa8e6, 0xf123, 0xf142, 0xf101, 0xa84f, 0x10d2, 0x70f6, 0x8832, + 0x8203, 0x870c, 0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b, + 0x9d6b, 0x2001, 0xa840, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834, + 0x8001, 0xa801, 0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218, + 0x6981, 0x9d57, 0x6b2a, 0x6902, 0x1834, 0xa805, 0x1814, 0x8010, + 0x8592, 0x8026, 0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9d44, + 0x694b, 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa80c, 0x8023, + 0x16e1, 0x8001, 0x10f1, 0x0016, 0x6969, 0xa214, 0x61c2, 0x8002, + 0x14e1, 0x8004, 0x16e1, 0x0101, 0x300a, 0x8827, 0x0014, 0xa217, + 0x9d57, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6, 0x882c, + 0x0016, 0xa212, 0x9d6b, 0x10d2, 0x70e4, 0x0004, 0x8007, 0x9424, + 0xcc1a, 0x9d6e, 0xa8f8, 0x8827, 0x300a, 0x0013, 0x8000, 0x84a4, + 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e, 0x0016, + 0xa21c, 0x1035, 0xa8b4, 0xa210, 0x3807, 0x300c, 0x817e, 0x872b, + 0x8772, 0xa8ad, 0x0000, 0x8ec6 }; #endif /* RELOAD_FIRMWARE */ -static const unsigned short risc_code_length01 = 0x283a; +static const unsigned short risc_code_length01 = 0x3f14; diff -u --recursive --new-file v2.2.6/linux/drivers/usb/CREDITS linux/drivers/usb/CREDITS --- v2.2.6/linux/drivers/usb/CREDITS Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/CREDITS Sat Apr 24 04:48:49 1999 @@ -0,0 +1,23 @@ +Credits for the Simple Linux USB Driver: + +The following people have contributed to this code (in alphabetical +order by last name). I'm sure this list should be longer, its +difficult to maintain. + + Johannes Erdfelt + ham + Bradley M Keryan + Vojtech Pavlik + Gregory P. Smith + Linus Torvalds + + +Special thanks to: + + Inaky Perez Gonzalez for starting the + Linux USB driver effort and writing much of the larger uusbd driver. + Much has been learned from that effort. + + The NetBSD & FreeBSD USB developers. For being on the Linux USB list + and offering suggestions and sharing implementation experiences. + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.2.6/linux/drivers/usb/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/Config.in Wed Apr 28 11:14:03 1999 @@ -0,0 +1,26 @@ +# +# USB device configuration +# +# NOTE NOTE NOTE! This is still considered extremely experimental. +# Right now hubs, mice and keyboards work - at least with UHCI. +# But that may be more a lucky coincidence than anything else.. +# +# This was all developed modularly, but I've been lazy in cleaning +# it up, so right now they are all bools. +# +mainmenu_option next_comment +comment 'USB drivers - not for the faint of heart' + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Support for USB (EXPERIMENTAL!)' CONFIG_USB + if [ ! "$CONFIG_USB" = "n" ]; then + bool 'UHCI (intel PIIX4 and others) support?' CONFIG_USB_UHCI + bool 'OHCI (compaq and some others) support?' CONFIG_USB_OHCI + + bool 'USB mouse support' CONFIG_USB_MOUSE + bool 'USB keyboard support' CONFIG_USB_KBD + bool 'USB audio parsing support' CONFIG_USB_AUDIO + fi +fi + +endmenu diff -u --recursive --new-file v2.2.6/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.2.6/linux/drivers/usb/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/Makefile Wed Apr 28 11:14:03 1999 @@ -0,0 +1,75 @@ +# +# Makefile for the kernel usb device drivers. +# +# 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 inherited from the +# parent makes.. +# +# This isn't actually supported yet. Don't try to use it. + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +L_TARGET := usb.a +M_OBJS := +L_OBJS := +LX_OBJS := +USBX_OBJS := usb.o hub.o usb-debug.o + +ifeq ($(CONFIG_USB_MOUSE),y) + USBX_OBJS += mouse.o +endif + +ifeq ($(CONFIG_USB_KBD),y) + USBX_OBJS += keyboard.o keymap.o +endif + +ifeq ($(CONFIG_USB_AUDIO),y) + USBX_OBJS += audio.o +endif + +ifeq ($(CONFIG_USB), y) + L_OBJS += $(USBX_OBJS) +endif + +ifeq ($(CONFIG_USB_UHCI),y) + ifeq ($(CONFIG_USB), y) + L_OBJS += uhci.o uhci-debug.o + else + ifeq ($(CONFIG_USB),m) + M_OBJS += usb-uhci.o + MIX_OBJS += $(USBX_OBJS) + endif + endif +endif + +ifeq ($(CONFIG_USB_OHCI),y) + ifeq ($(CONFIG_USB), y) + L_OBJS += ohci.o ohci-debug.o + else + ifeq ($(CONFIG_USB),m) + USBO_OBJS += ohci.o ohci-debug.o + M_OBJS += usb-ohci.o + MIX_OBJS += $(USBX_OBJS) + endif + endif +endif + + +include $(TOPDIR)/Rules.make + +keymap.o: keymap.c + +keymap.c: maps/serial.map maps/usb.map maps/fixup.map + ./mkmap > $@ + +usb-uhci.o: uhci.o uhci-debug.o $(USBX_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ uhci.o uhci-debug.o $(USBX_OBJS) + +usb-ohci.o: ohci.o ohci-debug.o $(USBX_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ ohci.o ohci-debug.o $(USBX_OBJS) + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/README.kbd linux/drivers/usb/README.kbd --- v2.2.6/linux/drivers/usb/README.kbd Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/README.kbd Wed Apr 21 10:29:09 1999 @@ -0,0 +1,65 @@ +This is a simple USB keyboard driver written from Linus' +USB driver (started with Greg's usb-0.03b.tar.gz source +tree) + +It works fine with my BTC keyboard but I'm still investigating +trouble with my MS keyboard (trouble starts with an inability +to set into boot protocol mode, though, this very well could +be all due to crappy hardware). + +Anyway, I would appreciate you taking a look if you have +any USB keyboards lying around. Oh also, I'm doing this on +UHCI so sorry if it breaks with OHCI. + +-ham + + + +Keyboard patch +-------------- + +Instead of using the multiple keyboard patch and then running into all +of the kernel version problems that the current Linux-USB project has +had, I'm just mapping the USB keycodes to the standard AT-101 keycodes +and sending them directly to "handle_scancode". + +This may or may not be considered a hack. Anyway it is effective, and +I think safe, and allows USB keyboards to coexist with a serial +keyboard (oh yeah, one side effect is that you can for example hold +down the control key on the serial keyboard and press "a" on the USB +keyboard and you get Control-a like with Windows USB) and works +fine for console and X. + +You do need to make a *tiny* patch the kernel source tree so that the +function "handle_scancode" is exported from keyboard.c though. + + $ cd /usr/src/linux + $ patch -p0 < kbd.patch + +And, of course, then, you need to rebuild and install the kernel. + +** [Vojtech]: Alternately, just 'insmod kbd-stub', if you don't want +to use the keyboard and are too lazy to patch the kernel. + +Keyboard map +------------ + +I'm including a stupid utility "mkmap" which generates the USB->serial +keymap. It takes in maps/serial.map (the current serial keymap, +generated by "dumpkeys"), maps/usb.map (the USB keymap), and +maps/fixup.map (fixes for e0 keys and misc.) and spits out keymap.c +Anyway, it is not beautiful but should serve its purpose for the +moment. + +Other changes +------------- +uhci.c: + * added a context value to the irq callback function + (this is exactly like the "dev_id" field to request_irq) + * played with uhci_reset_port to get better hot-plug results + (eg. do a wait_ms(200) before calling uhci_reset_port) +usb.c: + * disconnect all devices after uhci-control thread is killed + * skip over the HID descriptor + * disconnect the high-level driver in usb_disconnect + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/README.ohci linux/drivers/usb/README.ohci --- v2.2.6/linux/drivers/usb/README.ohci Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/README.ohci Sat Apr 24 04:40:07 1999 @@ -0,0 +1,8 @@ +April 24, 1999 04:37:42 PST + +Okay, I've written a lot more of the OHCI code and actually got it back to +a compiling state now with all of the recent improvements to the way stuff +is structured. It is completely untested. + +- greg@electricrain.com + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.2.6/linux/drivers/usb/audio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/audio.c Wed Apr 28 11:14:03 1999 @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include "usb.h" + +static int usb_audio_probe(struct usb_device *dev); +static void usb_audio_disconnect(struct usb_device *dev); +static LIST_HEAD(usb_audio_list); + +struct usb_audio +{ + struct usb_device *dev; + struct list_head list; +}; + +static struct usb_driver usb_audio_driver = +{ + "audio", + usb_audio_probe, + usb_audio_disconnect, + {NULL, NULL} +}; + + +static int usb_audio_irq(int state, void *buffer, void *dev_id) +{ + struct usb_audio *aud = (struct usb_audio*) dev_id; + return 1; +} + +static int usb_audio_probe(struct usb_device *dev) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_audio *aud; + + int i; + int na=0; + + interface = &dev->config[0].interface[0]; + + for(i=0;iconfig[0].bNumInterfaces;i++) + { + int x; + + endpoint = &interface->endpoint[i]; + + if(interface->bInterfaceClass != 1) + continue; + + printk(KERN_INFO "USB audio device detected.\n"); + + switch(interface->bInterfaceSubClass) + { + case 0x01: + printk(KERN_INFO "audio: Control device.\n"); + break; + case 0x02: + printk(KERN_INFO "audio: streaming.\n"); + break; + case 0x03: + printk(KERN_INFO "audio: nonstreaming.\n"); + break; + } + na++; + } + + if(na==0) + return -1; + + aud = kmalloc(sizeof(struct usb_audio), GFP_KERNEL); + if(aud) + { + memset(aud, 0, sizeof(*aud)); + aud->dev = dev; + dev->private = aud; + + endpoint = &interface->endpoint[0]; + +// usb_set_configuration(dev, dev->config[0].bConfigurationValue); +// usb_set_protocol(dev, 0); +// usb_set_idle(dev, 0, 0); + + usb_request_irq(dev, + usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), + usb_audio_irq, + endpoint->bInterval, + aud); + + list_add(&aud->list, &usb_audio_list); + } + return 0; +} + +static void usb_audio_disconnect(struct usb_device *dev) +{ + struct usb_audio *aud = (struct usb_audio*) dev->private; + if(aud) + { + dev->private = NULL; + list_del(&aud->list); + kfree(aud); + } + printk(KERN_INFO "USB audio driver removed.\n"); +} + +int usb_audio_init(void) +{ + usb_register(&usb_audio_driver); + return 0; +} + +/* + * Support functions for parsing + */ + +void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data) +{ +} + +void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data) +{ +} + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.2.6/linux/drivers/usb/hub.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/hub.c Sat Apr 24 17:11:41 1999 @@ -0,0 +1,409 @@ +/* + * USB hub driver. + * + * This is horrible, it knows about the UHCI driver + * internals, but it's just meant as a rough example, + * let's do the virtualization later when this works. + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + */ + +#include +#include +#include +#include +#include + +#include + +#include "usb.h" +#include "uhci.h" +#include "hub.h" + +extern struct usb_operations uhci_device_operations; + +/* Wakes up khubd */ +static struct wait_queue *usb_hub_wait = NULL; +static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; + +/* List of hubs needing servicing */ +static struct list_head hub_event_list; + +/* + * A irq handler returns non-zero to indicate to + * the low-level driver that it wants to be re-activated, + * or zero to say "I'm done". + */ +static int hub_irq(int status, void *__buffer, void *dev_id) +{ + struct usb_hub *hub = dev_id; + unsigned long flags; + + if (waitqueue_active(&usb_hub_wait)) { + /* Add the hub to the event queue */ + spin_lock_irqsave(&hub_event_lock, flags); + if (hub->event_list.next == &hub->event_list) { + list_add(&hub->event_list, &hub_event_list); + /* Wake up khubd */ + wake_up(&usb_hub_wait); + } + spin_unlock_irqrestore(&hub_event_lock, flags); + } + + return 1; +} + +static void usb_hub_configure(struct usb_hub *hub) +{ + struct usb_device *dev = hub->dev; + unsigned char hubdescriptor[8], buf[4]; + int charac, i; + + usb_set_configuration(dev, dev->config[0].bConfigurationValue); + + if (usb_get_hub_descriptor(dev, hubdescriptor, 8)) + return; + + hub->nports = dev->maxchild = hubdescriptor[2]; + printk("hub: %d-port%s detected\n", hub->nports, + (hub->nports == 1) ? "" : "s"); + + charac = (hubdescriptor[4] << 8) + hubdescriptor[3]; + switch (charac & HUB_CHAR_LPSM) { + case 0x00: + printk("hub: ganged power switching\n"); + break; + case 0x01: + printk("hub: individual port power switching\n"); + break; + case 0x02: + case 0x03: + printk("hub: unknown reserved power switching mode\n"); + break; + } + + if (charac & HUB_CHAR_COMPOUND) + printk("hub: part of a compound device\n"); + else + printk("hub: standalone hub\n"); + + switch (charac & HUB_CHAR_OCPM) { + case 0x00: + printk("hub: global over current protection\n"); + break; + case 0x08: + printk("hub: individual port over current protection\n"); + break; + case 0x10: + case 0x18: + printk("hub: no over current protection\n"); + break; + } + + printk("hub: power on to power good time: %dms\n", + hubdescriptor[5] * 2); + + printk("hub: hub controller current requirement: %dmA\n", + hubdescriptor[6]); + + for (i = 0; i < dev->maxchild; i++) + printk("hub: port %d is%s removable\n", i + 1, + hubdescriptor[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8)) + ? " not" : ""); + + if (usb_get_hub_status(dev, buf)) + return; + + printk("hub: local power source is %s\n", + (buf[0] & 1) ? "lost (inactive)" : "good"); + + printk("hub: %sover current condition exists\n", + (buf[0] & 2) ? "" : "no "); + +#if 0 + for (i = 0; i < hub->nports; i++) { + int portstat, portchange; + unsigned char portstatus[4]; + + if (usb_get_port_status(dev, i + 1, portstatus)) + return; + portstat = (portstatus[1] << 8) + portstatus[0]; + portchange = (portstatus[3] << 8) + portstatus[2]; + + printk("hub: port %d status\n", i + 1); + printk("hub: %sdevice present\n", (portstat & 1) ? "" : "no "); + printk("hub: %s\n", (portstat & 2) ? "enabled" : "disabled"); + printk("hub: %ssuspended\n", (portstat & 4) ? "" : "not "); + printk("hub: %sover current\n", (portstat & 8) ? "" : "not "); + printk("hub: has %spower\n", (portstat & 0x100) ? "" : "no "); + printk("hub: %s speed\n", (portstat & 0x200) ? "low" : "full"); + } +#endif + + /* Enable power to the ports */ + printk("enabling power on all ports\n"); + for (i = 0; i < hub->nports; i++) + usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); +} + +static int hub_probe(struct usb_device *dev) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_hub *hub; + + /* We don't handle multi-config hubs */ + if (dev->descriptor.bNumConfigurations != 1) + return -1; + + /* We don't handle multi-interface hubs */ + if (dev->config[0].bNumInterfaces != 1) + return -1; + + interface = &dev->config[0].interface[0]; + + /* Is it a hub? */ + if (interface->bInterfaceClass != 9) + return -1; + if (interface->bInterfaceSubClass != 0) + return -1; + + /* Multiple endpoints? What kind of mutant ninja-hub is this? */ + if (interface->bNumEndpoints != 1) + return -1; + + endpoint = &interface->endpoint[0]; + + /* Output endpoint? Curiousier and curiousier.. */ + if (!(endpoint->bEndpointAddress & 0x80)) + return -1; + + /* If it's not an interrupt endpoint, we'd better punt! */ + if ((endpoint->bmAttributes & 3) != 3) + return -1; + + /* We found a hub */ + printk("USB hub found\n"); + + if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) { + printk("couldn't kmalloc hub struct\n"); + return -1; + } + + memset(hub, 0, sizeof(*hub)); + + dev->private = hub; + + INIT_LIST_HEAD(&hub->event_list); + hub->dev = dev; + + usb_hub_configure(hub); + + usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub); + + /* Wake up khubd */ + wake_up(&usb_hub_wait); + + return 0; +} + +static void hub_disconnect(struct usb_device *dev) +{ + struct usb_hub *hub = dev->private; + unsigned long flags; + + spin_lock_irqsave(&hub_event_lock, flags); + + /* Delete it and then reset it */ + list_del(&hub->event_list); + INIT_LIST_HEAD(&hub->event_list); + + spin_unlock_irqrestore(&hub_event_lock, flags); + + /* Free the memory */ + kfree(hub); +} + +static void usb_hub_port_connect_change(struct usb_device *hub, int port) +{ + struct usb_device *usb; + unsigned char buf[4]; + unsigned short portstatus, portchange; + + usb_disconnect(&hub->children[port]); + + usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); + + wait_ms(50); /* FIXME: This is from the *BSD stack, thanks! :) */ + + if (usb_get_port_status(hub, port + 1, buf)) { + printk("get_port_status failed\n"); + return; + } + + portstatus = *((unsigned short *)buf + 0); + portchange = *((unsigned short *)buf + 1); + + if ((!(portstatus & USB_PORT_STAT_CONNECTION)) && + (!(portstatus & USB_PORT_STAT_ENABLE))) { + /* We're done now, we already disconnected the device */ + /* printk("not connected/enabled\n"); */ + return; + } + + usb = hub->bus->op->allocate(hub); + if (!usb) { + printk("couldn't allocate usb_device\n"); + return; + } + + usb_connect(usb); + + usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0; + + hub->children[port] = usb; + + usb_new_device(usb); +} + +static void usb_hub_events(void) +{ + unsigned long flags; + unsigned char buf[4]; + unsigned short portstatus, portchange; + int i; + struct list_head *next, *tmp, *head = &hub_event_list; + struct usb_device *dev; + struct usb_hub *hub; + + spin_lock_irqsave(&hub_event_lock, flags); + + tmp = head->next; + while (tmp != head) { + hub = list_entry(tmp, struct usb_hub, event_list); + dev = hub->dev; + + next = tmp->next; + + list_del(tmp); + INIT_LIST_HEAD(tmp); + + for (i = 0; i < hub->nports; i++) { + if (usb_get_port_status(dev, i + 1, buf)) { + printk("get_port_status failed\n"); + continue; + } + + portstatus = *((unsigned short *)buf + 0); + portchange = *((unsigned short *)buf + 1); + + if (portchange & USB_PORT_STAT_C_CONNECTION) { + printk("hub: port %d connection change\n", i + 1); + + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_CONNECTION); + + usb_hub_port_connect_change(dev, i); + } + + if (portchange & USB_PORT_STAT_C_ENABLE) { + printk("hub: port %d enable change\n", i + 1); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_ENABLE); + } + + if (portchange & USB_PORT_STAT_C_SUSPEND) + printk("hub: port %d suspend change\n", i + 1); + + if (portchange & USB_PORT_STAT_C_OVERCURRENT) + printk("hub: port %d over-current change\n", i + 1); + + if (portchange & USB_PORT_STAT_C_RESET) { + printk("hub: port %d reset change\n", i + 1); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_RESET); + } + +#if 0 + if (!portchange) + continue; + + if (usb_get_port_status(dev, i + 1, buf)) + return; + + portstatus = (buf[1] << 8) + buf[0]; + portchange = (buf[3] << 8) + buf[2]; + + printk("hub: port %d status\n", i + 1); + printk("hub: %sdevice present\n", (portstatus & 1) ? "" : "no "); + printk("hub: %s\n", (portstatus & 2) ? "enabled" : "disabled"); + printk("hub: %ssuspended\n", (portstatus & 4) ? "" : "not "); + printk("hub: %sover current\n", (portstatus & 8) ? "" : "not "); + printk("hub: has %spower\n", (portstatus & 0x100) ? "" : "no "); + printk("hub: %s speed\n", (portstatus & 0x200) ? "low" : "full"); +#endif + } + tmp = next; +#if 0 + wait_ms(1000); +#endif + } + + spin_unlock_irqrestore(&hub_event_lock, flags); +} + +static int usb_hub_thread(void *__hub) +{ + lock_kernel(); + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources + */ + printk("usb_hub_thread at %p\n", &usb_hub_thread); + exit_mm(current); + exit_files(current); + exit_fs(current); + + /* Setup a nice name */ + strcpy(current->comm, "khubd"); + + /* Send me a signal to get me die (for debugging) */ + do { + interruptible_sleep_on(&usb_hub_wait); + usb_hub_events(); + } while (!signal_pending(current)); + + printk("usb_hub_thread exiting\n"); + + return 0; +} + +static struct usb_driver hub_driver = { + "hub", + hub_probe, + hub_disconnect, + { NULL, NULL } +}; + +/* + * This should be a separate module. + */ +int hub_init(void) +{ + int pid; + + INIT_LIST_HEAD(&hub_event_list); + + usb_register(&hub_driver); + pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (pid >= 0) + return 0; + + /* Fall through if kernel_thread failed */ + usb_deregister(&hub_driver); + + return 0; +} + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/hub.h linux/drivers/usb/hub.h --- v2.2.6/linux/drivers/usb/hub.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/hub.h Wed Apr 21 05:41:59 1999 @@ -0,0 +1,80 @@ +#ifndef __LINUX_HUB_H +#define __LINUX_HUB_H + +#include + +/* + * Hub feature numbers + */ +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 + +/* + * Port feature numbers + */ +#define USB_PORT_FEAT_ENABLE 1 +#define USB_PORT_FEAT_SUSPEND 2 +#define USB_PORT_FEAT_OVER_CURRENT 3 +#define USB_PORT_FEAT_RESET 4 +#define USB_PORT_FEAT_POWER 8 +#define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_C_CONNECTION 16 +#define USB_PORT_FEAT_C_ENABLE 17 +#define USB_PORT_FEAT_C_SUSPEND 18 +#define USB_PORT_FEAT_C_OVER_CURRENT 19 +#define USB_PORT_FEAT_C_RESET 20 + +/* wPortStatus */ +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 + +/* wPortChange */ +#define USB_PORT_STAT_C_CONNECTION 0x0001 +#define USB_PORT_STAT_C_ENABLE 0x0002 +#define USB_PORT_STAT_C_SUSPEND 0x0004 +#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +#define USB_PORT_STAT_C_RESET 0x0010 + +/* Characteristics */ +#define HUB_CHAR_LPSM 0x0003 +#define HUB_CHAR_COMPOUND 0x0004 +#define HUB_CHAR_OCPM 0x0018 + +struct usb_device; + +typedef enum { + USB_PORT_UNPOWERED = 0, /* Default state */ + USB_PORT_POWERED, /* When we've put power to it */ + USB_PORT_ENABLED, /* When it's been enabled */ + USB_PORT_DISABLED, /* If it's been disabled */ + USB_PORT_ADMINDISABLED, /* Forced down */ +} usb_hub_port_state; + +struct usb_hub_port { + usb_hub_port_state cstate; /* Configuration state */ + + struct usb_device *child; /* Device attached to this port */ + + struct usb_hub *parent; /* Parent hub */ +}; + +struct usb_hub { + /* Device structure */ + struct usb_device *dev; + + /* Temporary event list */ + struct list_head event_list; + + /* Number of ports on the hub */ + int nports; + + struct usb_hub_port ports[0]; /* Dynamically allocated */ +}; + +#endif + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/inits.h linux/drivers/usb/inits.h --- v2.2.6/linux/drivers/usb/inits.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/inits.h Wed Apr 28 11:14:03 1999 @@ -0,0 +1,4 @@ +int bp_mouse_init(void); +int usb_kbd_init(void); +int usb_audio_init(void); +int hub_init(void); diff -u --recursive --new-file v2.2.6/linux/drivers/usb/keyboard.c linux/drivers/usb/keyboard.c --- v2.2.6/linux/drivers/usb/keyboard.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/keyboard.c Mon Apr 26 13:35:01 1999 @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include "usb.h" + +#define PCKBD_PRESSED 0x00 +#define PCKBD_RELEASED 0x80 +#define PCKBD_NEEDS_E0 0x80 + +#define USBKBD_MODIFIER_BASE 120 +#define USBKBD_KEYCODE_OFFSET 2 +#define USBKBD_KEYCODE_COUNT 6 + +#define USBKBD_VALID_KEYCODE(key) ((unsigned char)(key) > 3) +#define USBKBD_FIND_KEYCODE(down, key, count) \ + ((unsigned char*) memscan((down), (key), (count)) < ((down) + (count))) + +#define USBKBD_REPEAT_DELAY (HZ / 4) +#define USBKBD_REPEAT_RATE (HZ / 20) + +struct usb_keyboard +{ + struct usb_device *dev; + unsigned long down[2]; + unsigned char repeat_key; + struct timer_list repeat_timer; + struct list_head list; +}; + +extern unsigned char usb_kbd_map[]; + +static int usb_kbd_probe(struct usb_device *dev); +static void usb_kbd_disconnect(struct usb_device *dev); +static void usb_kbd_repeat(unsigned long dummy); + +static LIST_HEAD(usb_kbd_list); + +static struct usb_driver usb_kbd_driver = +{ + "keyboard", + usb_kbd_probe, + usb_kbd_disconnect, + {NULL, NULL} +}; + + +static void +usb_kbd_handle_key(unsigned char key, int down) +{ + int scancode = (int) usb_kbd_map[key]; + if(scancode) + { + if(scancode & PCKBD_NEEDS_E0) + { + handle_scancode(0xe0, 1); + } + handle_scancode((scancode & ~PCKBD_NEEDS_E0), down); + } +} + +static void +usb_kbd_repeat(unsigned long dev_id) +{ + struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id; + + unsigned long flags; + save_flags(flags); + cli(); + + if(kbd->repeat_key) + { + usb_kbd_handle_key(kbd->repeat_key, 1); + + /* reset repeat timer */ + kbd->repeat_timer.function = usb_kbd_repeat; + kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_RATE; + kbd->repeat_timer.data = (unsigned long) kbd; + kbd->repeat_timer.prev = NULL; + kbd->repeat_timer.next = NULL; + add_timer(&kbd->repeat_timer); + } + + restore_flags(flags); +} + +static int +usb_kbd_irq(int state, void *buffer, void *dev_id) +{ + struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id; + unsigned long *down = (unsigned long*) buffer; + + if(kbd->down[0] != down[0] || kbd->down[1] != down[1]) + { + unsigned char *olddown, *newdown; + unsigned char modsdelta, key; + int i; + + /* handle modifier change */ + modsdelta = (*(unsigned char*) down ^ *(unsigned char*) kbd->down); + if(modsdelta) + { + for(i = 0; i < 8; i++) + { + if(modsdelta & 0x01) + { + int pressed = (*(unsigned char*) down >> i) & 0x01; + usb_kbd_handle_key( + i + USBKBD_MODIFIER_BASE, + pressed); + } + modsdelta >>= 1; + } + } + + olddown = (unsigned char*) kbd->down + USBKBD_KEYCODE_OFFSET; + newdown = (unsigned char*) down + USBKBD_KEYCODE_OFFSET; + + /* handle released keys */ + for(i = 0; i < USBKBD_KEYCODE_COUNT; i++) + { + key = olddown[i]; + if(USBKBD_VALID_KEYCODE(key) + && !USBKBD_FIND_KEYCODE(newdown, key, USBKBD_KEYCODE_COUNT)) + { + usb_kbd_handle_key(key, 0); + } + } + + /* handle pressed keys */ + kbd->repeat_key = 0; + for(i = 0; i < USBKBD_KEYCODE_COUNT; i++) + { + key = newdown[i]; + if(USBKBD_VALID_KEYCODE(key) + && !USBKBD_FIND_KEYCODE(olddown, key, USBKBD_KEYCODE_COUNT)) + { + usb_kbd_handle_key(key, 1); + kbd->repeat_key = key; + } + } + + /* set repeat timer if any keys were pressed */ + if(kbd->repeat_key) + { + del_timer(&kbd->repeat_timer); + kbd->repeat_timer.function = usb_kbd_repeat; + kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_DELAY; + kbd->repeat_timer.data = (unsigned long) kbd; + kbd->repeat_timer.prev = NULL; + kbd->repeat_timer.next = NULL; + add_timer(&kbd->repeat_timer); + } + + kbd->down[0] = down[0]; + kbd->down[1] = down[1]; + } + + return 1; +} + +static int +usb_kbd_probe(struct usb_device *dev) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_keyboard *kbd; + + interface = &dev->config[0].interface[0]; + endpoint = &interface->endpoint[0]; + + if(interface->bInterfaceClass != 3 + || interface->bInterfaceSubClass != 1 + || interface->bInterfaceProtocol != 1) + { + return -1; + } + + printk(KERN_INFO "USB HID boot protocol keyboard detected.\n"); + + kbd = kmalloc(sizeof(struct usb_keyboard), GFP_KERNEL); + if(kbd) + { + memset(kbd, 0, sizeof(*kbd)); + kbd->dev = dev; + dev->private = kbd; + + usb_set_configuration(dev, dev->config[0].bConfigurationValue); + usb_set_protocol(dev, 0); + usb_set_idle(dev, 0, 0); + + usb_request_irq(dev, + usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), + usb_kbd_irq, + endpoint->bInterval, + kbd); + + list_add(&kbd->list, &usb_kbd_list); + } + + return 0; +} + +static void +usb_kbd_disconnect(struct usb_device *dev) +{ + struct usb_keyboard *kbd = (struct usb_keyboard*) dev->private; + if(kbd) + { + dev->private = NULL; + list_del(&kbd->list); + del_timer(&kbd->repeat_timer); + kfree(kbd); + } + + printk(KERN_INFO "USB HID boot protocol keyboard removed.\n"); +} + +int +usb_kbd_init(void) +{ + usb_register(&usb_kbd_driver); + return 0; +} diff -u --recursive --new-file v2.2.6/linux/drivers/usb/keymap.c linux/drivers/usb/keymap.c --- v2.2.6/linux/drivers/usb/keymap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/keymap.c Mon Apr 26 12:19:05 1999 @@ -0,0 +1,50 @@ +unsigned char usb_kbd_map[256] = +{ + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x2e, 0x20, + 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, + + 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, + 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, + + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x1c, 0x01, 0xd3, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, + + 0x1b, 0x2b, 0x00, 0x27, 0x28, 0x29, 0x33, 0x34, + 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + + 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xb7, 0x46, + 0x00, 0xd2, 0xc7, 0xc9, 0x63, 0xcf, 0xd1, 0xcd, + + 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, + 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, + + 0x48, 0x49, 0x52, 0x53, 0x00, 0x6d, 0x00, 0x00, + 0xbd, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff -u --recursive --new-file v2.2.6/linux/drivers/usb/maps/fixup.map linux/drivers/usb/maps/fixup.map --- v2.2.6/linux/drivers/usb/maps/fixup.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/maps/fixup.map Fri Apr 16 15:38:24 1999 @@ -0,0 +1,31 @@ +# misc fixes +keycode 0 = Pause +keycode 29 = Control +keycode 99 = Remove +keycode 42 = Shift +keycode 54 = Shift_R +keycode 109 = Application + +# E0 keys (or'ed with 0x80) +keycode 156 = KP_Enter +keycode 157 = Control_R +keycode 181 = KP_Divide +keycode 183 = Print_Screen +keycode 184 = Alt_R +keycode 189 = F13 +keycode 190 = F14 +keycode 193 = F17 +keycode 198 = Break +keycode 199 = Home +keycode 200 = Up +keycode 201 = Prior +keycode 203 = Left +keycode 205 = Right +keycode 207 = End +keycode 208 = Down +keycode 209 = Next +keycode 210 = Insert +keycode 211 = Delete +keycode 219 = Window +keycode 220 = Window_R +keycode 221 = Menu diff -u --recursive --new-file v2.2.6/linux/drivers/usb/maps/serial.map linux/drivers/usb/maps/serial.map --- v2.2.6/linux/drivers/usb/maps/serial.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/maps/serial.map Mon Apr 19 11:47:54 1999 @@ -0,0 +1,370 @@ +keymaps 0-2,4-6,8-9,12 +keycode 1 = Escape + alt keycode 1 = Meta_Escape + shift alt keycode 1 = Meta_Escape + control alt keycode 1 = Meta_Escape +keycode 2 = one exclam + alt keycode 2 = Meta_one + shift alt keycode 2 = Meta_exclam +keycode 3 = two at at nul nul + alt keycode 3 = Meta_two + shift alt keycode 3 = Meta_at + control alt keycode 3 = Meta_nul +keycode 4 = three numbersign + control keycode 4 = Escape + alt keycode 4 = Meta_three + shift alt keycode 4 = Meta_numbersign +keycode 5 = four dollar dollar Control_backslash + alt keycode 5 = Meta_four + shift alt keycode 5 = Meta_dollar + control alt keycode 5 = Meta_Control_backslash +keycode 6 = five percent + control keycode 6 = Control_bracketright + alt keycode 6 = Meta_five + shift alt keycode 6 = Meta_percent +keycode 7 = six asciicircum + control keycode 7 = Control_asciicircum + alt keycode 7 = Meta_six + shift alt keycode 7 = Meta_asciicircum +keycode 8 = seven ampersand braceleft Control_underscore + alt keycode 8 = Meta_seven + shift alt keycode 8 = Meta_ampersand + control alt keycode 8 = Meta_Control_underscore +keycode 9 = eight asterisk bracketleft Delete + alt keycode 9 = Meta_eight + shift alt keycode 9 = Meta_asterisk + control alt keycode 9 = Meta_Delete +keycode 10 = nine parenleft bracketright + alt keycode 10 = Meta_nine + shift alt keycode 10 = Meta_parenleft +keycode 11 = zero parenright braceright + alt keycode 11 = Meta_zero + shift alt keycode 11 = Meta_parenright +keycode 12 = minus underscore backslash Control_underscore Control_underscore + alt keycode 12 = Meta_minus + shift alt keycode 12 = Meta_underscore + control alt keycode 12 = Meta_Control_underscore +keycode 13 = equal plus + alt keycode 13 = Meta_equal + shift alt keycode 13 = Meta_plus +keycode 14 = Delete + alt keycode 14 = Meta_Delete + shift alt keycode 14 = Meta_Delete + control alt keycode 14 = Meta_Delete +keycode 15 = Tab + alt keycode 15 = Meta_Tab + shift alt keycode 15 = Meta_Tab + control alt keycode 15 = Meta_Tab +keycode 16 = q +keycode 17 = w +keycode 18 = e +keycode 19 = r +keycode 20 = t +keycode 21 = y +keycode 22 = u +keycode 23 = i +keycode 24 = o +keycode 25 = p +keycode 26 = bracketleft braceleft + control keycode 26 = Escape + alt keycode 26 = Meta_bracketleft + shift alt keycode 26 = Meta_braceleft +keycode 27 = bracketright braceright asciitilde Control_bracketright + alt keycode 27 = Meta_bracketright + shift alt keycode 27 = Meta_braceright + control alt keycode 27 = Meta_Control_bracketright +keycode 28 = Return + alt keycode 28 = Meta_Control_m +keycode 29 = Control +keycode 30 = a +keycode 31 = s +keycode 32 = d +keycode 33 = f +keycode 34 = g +keycode 35 = h +keycode 36 = j +keycode 37 = k +keycode 38 = l +keycode 39 = semicolon colon + alt keycode 39 = Meta_semicolon + shift alt keycode 39 = Meta_colon +keycode 40 = apostrophe quotedbl + control keycode 40 = Control_g + alt keycode 40 = Meta_apostrophe + shift alt keycode 40 = Meta_quotedbl +keycode 41 = grave asciitilde + control keycode 41 = nul + alt keycode 41 = Meta_grave + shift alt keycode 41 = Meta_asciitilde +keycode 42 = Shift +keycode 43 = backslash bar + control keycode 43 = Control_backslash + alt keycode 43 = Meta_backslash + shift alt keycode 43 = Meta_bar +keycode 44 = z +keycode 45 = x +keycode 46 = c +keycode 47 = v +keycode 48 = b +keycode 49 = n +keycode 50 = m +keycode 51 = comma less + alt keycode 51 = Meta_comma + shift alt keycode 51 = Meta_less +keycode 52 = period greater + alt keycode 52 = Meta_period + shift alt keycode 52 = Meta_greater +keycode 53 = slash question + control keycode 53 = Delete + alt keycode 53 = Meta_slash + shift alt keycode 53 = Meta_question +keycode 54 = Shift +keycode 55 = KP_Multiply + altgr keycode 55 = Hex_C +keycode 56 = Alt +keycode 57 = space + control keycode 57 = nul + alt keycode 57 = Meta_space + shift alt keycode 57 = Meta_space + control alt keycode 57 = Meta_nul +keycode 58 = Caps_Lock +keycode 59 = F1 F13 Console_13 F25 + alt keycode 59 = Console_1 + control alt keycode 59 = Console_1 +keycode 60 = F2 F14 Console_14 F26 + alt keycode 60 = Console_2 + control alt keycode 60 = Console_2 +keycode 61 = F3 F15 Console_15 F27 + alt keycode 61 = Console_3 + control alt keycode 61 = Console_3 +keycode 62 = F4 F16 Console_16 F28 + alt keycode 62 = Console_4 + control alt keycode 62 = Console_4 +keycode 63 = F5 F17 Console_17 F29 + alt keycode 63 = Console_5 + control alt keycode 63 = Console_5 +keycode 64 = F6 F18 Console_18 F30 + alt keycode 64 = Console_6 + control alt keycode 64 = Console_6 +keycode 65 = F7 F19 Console_19 F31 + alt keycode 65 = Console_7 + control alt keycode 65 = Console_7 +keycode 66 = F8 F20 Console_20 F32 + alt keycode 66 = Console_8 + control alt keycode 66 = Console_8 +keycode 67 = F9 F21 Console_21 F33 + alt keycode 67 = Console_9 + control alt keycode 67 = Console_9 +keycode 68 = F10 F22 Console_22 F34 + alt keycode 68 = Console_10 + control alt keycode 68 = Console_10 +keycode 69 = Num_Lock + altgr keycode 69 = Hex_E +keycode 70 = Scroll_Lock Show_Memory Show_Registers Show_State + alt keycode 70 = Scroll_Lock +keycode 71 = KP_7 + altgr keycode 71 = Hex_7 + alt keycode 71 = Ascii_7 +keycode 72 = KP_8 + altgr keycode 72 = Hex_8 + alt keycode 72 = Ascii_8 +keycode 73 = KP_9 + altgr keycode 73 = Hex_9 + alt keycode 73 = Ascii_9 +keycode 74 = KP_Subtract +keycode 75 = KP_4 + altgr keycode 75 = Hex_4 + alt keycode 75 = Ascii_4 +keycode 76 = KP_5 + altgr keycode 76 = Hex_5 + alt keycode 76 = Ascii_5 +keycode 77 = KP_6 + altgr keycode 77 = Hex_6 + alt keycode 77 = Ascii_6 +keycode 78 = KP_Add +keycode 79 = KP_1 + altgr keycode 79 = Hex_1 + alt keycode 79 = Ascii_1 +keycode 80 = KP_2 + altgr keycode 80 = Hex_2 + alt keycode 80 = Ascii_2 +keycode 81 = KP_3 + altgr keycode 81 = Hex_3 + alt keycode 81 = Ascii_3 +keycode 82 = KP_0 + altgr keycode 82 = Hex_0 + alt keycode 82 = Ascii_0 +keycode 83 = KP_Period + altgr control keycode 83 = Boot + control alt keycode 83 = Boot +keycode 84 = Last_Console +keycode 85 = +keycode 86 = less greater bar + alt keycode 86 = Meta_less + shift alt keycode 86 = Meta_greater +keycode 87 = F11 F23 Console_23 F35 + alt keycode 87 = Console_11 + control alt keycode 87 = Console_11 +keycode 88 = F12 F24 Console_24 F36 + alt keycode 88 = Console_12 + control alt keycode 88 = Console_12 +keycode 89 = +keycode 90 = +keycode 91 = +keycode 92 = +keycode 93 = +keycode 94 = +keycode 95 = +keycode 96 = KP_Enter +keycode 97 = Control +keycode 98 = KP_Divide + altgr keycode 98 = Hex_B +keycode 99 = Control_backslash + alt keycode 99 = Meta_Control_backslash + shift alt keycode 99 = Meta_Control_backslash + control alt keycode 99 = Meta_Control_backslash +keycode 100 = AltGr +keycode 101 = Break +keycode 102 = Find +keycode 103 = Up + alt keycode 103 = KeyboardSignal +keycode 104 = Prior + shift keycode 104 = Scroll_Backward +keycode 105 = Left + alt keycode 105 = Decr_Console +keycode 106 = Right + alt keycode 106 = Incr_Console +keycode 107 = Select +keycode 108 = Down +keycode 109 = Next + shift keycode 109 = Scroll_Forward +keycode 110 = Insert +keycode 111 = Remove + altgr control keycode 111 = Boot + control alt keycode 111 = Boot +keycode 112 = Macro + altgr control keycode 112 = VoidSymbol + shift alt keycode 112 = VoidSymbol +keycode 113 = F13 + altgr control keycode 113 = VoidSymbol + shift alt keycode 113 = VoidSymbol +keycode 114 = F14 + altgr control keycode 114 = VoidSymbol + shift alt keycode 114 = VoidSymbol +keycode 115 = Help + altgr control keycode 115 = VoidSymbol + shift alt keycode 115 = VoidSymbol +keycode 116 = Do + altgr control keycode 116 = VoidSymbol + shift alt keycode 116 = VoidSymbol +keycode 117 = F17 + altgr control keycode 117 = VoidSymbol + shift alt keycode 117 = VoidSymbol +keycode 118 = KP_MinPlus + altgr control keycode 118 = VoidSymbol + shift alt keycode 118 = VoidSymbol +keycode 119 = Pause +keycode 120 = +keycode 121 = +keycode 122 = +keycode 123 = +keycode 124 = +keycode 125 = +keycode 126 = +keycode 127 = +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.2.6/linux/drivers/usb/maps/usb.map linux/drivers/usb/maps/usb.map --- v2.2.6/linux/drivers/usb/maps/usb.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/maps/usb.map Fri Apr 16 15:38:24 1999 @@ -0,0 +1,233 @@ +# USB kernel keymap. +keymaps 0-2,4-5,8,12 + +keycode 4 = a + altgr keycode 30 = Hex_A +keycode 5 = b + altgr keycode 48 = Hex_B +keycode 6 = c + altgr keycode 46 = Hex_C +keycode 7 = d + altgr keycode 32 = Hex_D +keycode 8 = e + altgr keycode 18 = Hex_E +keycode 9 = f + altgr keycode 33 = Hex_F +keycode 10 = g +keycode 11 = h +keycode 12 = i +keycode 13 = j +keycode 14 = k +keycode 15 = l +keycode 16 = m +keycode 17 = n +keycode 18 = o +keycode 19 = p +keycode 20 = q +keycode 21 = r +keycode 22 = s +keycode 23 = t +keycode 24 = u +keycode 25 = v +keycode 26 = w +keycode 27 = x +keycode 28 = y +keycode 29 = z +keycode 30 = one exclam + alt keycode 2 = Meta_one +keycode 31 = two at + control keycode 3 = nul + shift control keycode 3 = nul + alt keycode 3 = Meta_two +keycode 32 = three numbersign + control keycode 4 = Escape + alt keycode 4 = Meta_three +keycode 33 = four dollar + control keycode 5 = Control_backslash + alt keycode 5 = Meta_four +keycode 34 = five percent + control keycode 6 = Control_bracketright + alt keycode 6 = Meta_five +keycode 35 = six asciicircum + control keycode 7 = Control_asciicircum + alt keycode 7 = Meta_six +keycode 36 = seven ampersand + control keycode 8 = Control_underscore + alt keycode 8 = Meta_seven +keycode 37 = eight asterisk + control keycode 9 = Delete + alt keycode 9 = Meta_eight +keycode 38 = nine parenleft + alt keycode 10 = Meta_nine +keycode 39 = zero parenright + alt keycode 11 = Meta_zero +keycode 40 = Return + alt keycode 28 = Meta_Control_m +keycode 41 = Escape Escape + alt keycode 1 = Meta_Escape +keycode 42 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete +keycode 43 = Tab Tab + alt keycode 15 = Meta_Tab +keycode 44 = space space + control keycode 57 = nul + alt keycode 57 = Meta_space +keycode 45 = minus underscore backslash + control keycode 12 = Control_underscore + shift control keycode 12 = Control_underscore + alt keycode 12 = Meta_minus +keycode 46 = equal plus + alt keycode 13 = Meta_equal +keycode 47 = bracketleft braceleft + control keycode 26 = Escape + alt keycode 26 = Meta_bracketleft +keycode 48 = bracketright braceright asciitilde + control keycode 27 = Control_bracketright + alt keycode 27 = Meta_bracketright +keycode 49 = backslash bar + control keycode 43 = Control_backslash + alt keycode 43 = Meta_backslash +keycode 50 = +keycode 51 = semicolon colon + alt keycode 39 = Meta_semicolon +keycode 52 = apostrophe quotedbl + control keycode 40 = Control_g + alt keycode 40 = Meta_apostrophe +keycode 53 = grave asciitilde + control keycode 41 = nul + alt keycode 41 = Meta_grave +keycode 54 = comma less + alt keycode 51 = Meta_comma +keycode 55 = period greater + control keycode 52 = Compose + alt keycode 52 = Meta_period +keycode 56 = slash question + control keycode 53 = Delete + alt keycode 53 = Meta_slash +keycode 57 = Caps_Lock +keycode 58 = F1 F11 Console_13 + control keycode 59 = F1 + alt keycode 59 = Console_1 + control alt keycode 59 = Console_1 +keycode 59 = F2 F12 Console_14 + control keycode 60 = F2 + alt keycode 60 = Console_2 + control alt keycode 60 = Console_2 +keycode 60 = F3 F13 Console_15 + control keycode 61 = F3 + alt keycode 61 = Console_3 + control alt keycode 61 = Console_3 +keycode 61 = F4 F14 Console_16 + control keycode 62 = F4 + alt keycode 62 = Console_4 + control alt keycode 62 = Console_4 +keycode 62 = F5 F15 Console_17 + control keycode 63 = F5 + alt keycode 63 = Console_5 + control alt keycode 63 = Console_5 +keycode 63 = F6 F16 Console_18 + control keycode 64 = F6 + alt keycode 64 = Console_6 + control alt keycode 64 = Console_6 +keycode 64 = F7 F17 Console_19 + control keycode 65 = F7 + alt keycode 65 = Console_7 + control alt keycode 65 = Console_7 +keycode 65 = F8 F18 Console_20 + control keycode 66 = F8 + alt keycode 66 = Console_8 + control alt keycode 66 = Console_8 +keycode 66 = F9 F19 Console_21 + control keycode 67 = F9 + alt keycode 67 = Console_9 + control alt keycode 67 = Console_9 +keycode 67 = F10 F20 Console_22 + control keycode 68 = F10 + alt keycode 68 = Console_10 + control alt keycode 68 = Console_10 +keycode 68 = F11 F11 Console_23 + control keycode 87 = F11 + alt keycode 87 = Console_11 + control alt keycode 87 = Console_11 +keycode 69 = F12 F12 Console_24 + control keycode 88 = F12 + alt keycode 88 = Console_12 + control alt keycode 88 = Console_12 +keycode 70 = Print_Screen +keycode 71 = Scroll_Lock Show_Memory Show_Registers + control keycode 70 = Show_State + alt keycode 70 = Scroll_Lock +keycode 72 = Pause +keycode 73 = Insert +keycode 74 = Home +keycode 75 = Prior + shift keycode 104 = Scroll_Backward +keycode 76 = Remove +# altgr control keycode 111 = Boot + control alt keycode 111 = Boot +keycode 77 = End +keycode 78 = Next + shift keycode 109 = Scroll_Forward +keycode 79 = Right + alt keycode 106 = Incr_Console +keycode 80 = Left + alt keycode 105 = Decr_Console +keycode 81 = Down +keycode 82 = Up +keycode 83 = Num_Lock + shift keycode 69 = Bare_Num_Lock +keycode 84 = KP_Divide +keycode 85 = KP_Multiply +keycode 86 = KP_Subtract +keycode 87 = KP_Add +keycode 88 = KP_Enter +keycode 89 = KP_1 + alt keycode 79 = Ascii_1 + altgr keycode 79 = Hex_1 +keycode 90 = KP_2 + alt keycode 80 = Ascii_2 + altgr keycode 80 = Hex_2 +keycode 91 = KP_3 + alt keycode 81 = Ascii_3 + altgr keycode 81 = Hex_3 +keycode 92 = KP_4 + alt keycode 75 = Ascii_4 + altgr keycode 75 = Hex_4 +keycode 93 = KP_5 + alt keycode 76 = Ascii_5 + altgr keycode 76 = Hex_5 +keycode 94 = KP_6 + alt keycode 77 = Ascii_6 + altgr keycode 77 = Hex_6 +keycode 95 = KP_7 + alt keycode 71 = Ascii_7 + altgr keycode 71 = Hex_7 +keycode 96 = KP_8 + alt keycode 72 = Ascii_8 + altgr keycode 72 = Hex_8 +keycode 97 = KP_9 + alt keycode 73 = Ascii_9 + altgr keycode 73 = Hex_9 +keycode 98 = KP_0 + alt keycode 82 = Ascii_0 + altgr keycode 82 = Hex_0 +keycode 99 = KP_Period +# altgr control keycode 83 = Boot + control alt keycode 83 = Boot +keycode 100 = +keycode 101 = Application +keycode 102 = +keycode 103 = +keycode 104 = F13 +keycode 105 = F14 + +# modifiers +keycode 120 = Control +keycode 121 = Shift +keycode 122 = Alt +keycode 123 = Window +keycode 124 = Control_R +keycode 125 = Shift_R +keycode 126 = Alt_R +keycode 127 = Window_R diff -u --recursive --new-file v2.2.6/linux/drivers/usb/mkmap linux/drivers/usb/mkmap --- v2.2.6/linux/drivers/usb/mkmap Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/mkmap Mon Apr 19 11:53:27 1999 @@ -0,0 +1,83 @@ +#!/usr/bin/perl + +($ME = $0) =~ s|.*/||; + +$file = "maps/serial.map"; +$line = 1; +open(PC, $file) || die("$!"); +while() +{ + if(/^\s*keycode\s+(\d+)\s*=\s*(\S+)/) + { + my($idx) = int($1); + my($sym) = $2; + if(defined($map{uc($sym)})) + { + # print STDERR "$file:$line: warning: `$sym' redefined\n"; + } + $map{uc($sym)} = $idx; + } + $line++; +} +close(PC); + +$file = "maps/fixup.map"; +$line = 1; +open(FIXUP, $file) || die("$!"); +while() +{ + if(/^\s*keycode\s+(\d+)\s*=\s*/) + { + my($idx) = int($1); + for $sym (split(/\s+/, $')) + { + $map{uc($sym)} = $idx; + } + } + $line++; +} +close(FIXUP); + +$file = "maps/usb.map"; +$line = 1; +open(USB, $file) || die("$!"); +while() +{ + if(/^\s*keycode\s+(\d+)\s*=\s*/) + { + my($idx) = int($1); + for $sym (split(/\s+/, $')) + { + my($val) = $map{uc($sym)}; + $map[$idx] = $val; + if(!defined($val)) + { + print STDERR "$file:$line: warning: `$sym' undefined\n"; + } + else + { + last; + } + } + } + $line++; +} +close(USB); + +print "unsigned char usb_kbd_map[256] = \n{\n"; +for($x = 0; $x < 32; $x++) +{ + if($x && !($x % 2)) + { + print "\n"; + } + print " "; + for($y = 0; $y < 8; $y++) + { + my($idx) = $x * 8 + $y; + print sprintf(" 0x%02x,", + int(defined($map[$idx]) ? $map[$idx]:0)); + } + print "\n"; +} +print "};\n"; diff -u --recursive --new-file v2.2.6/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c --- v2.2.6/linux/drivers/usb/mouse.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/mouse.c Sat Apr 24 17:11:41 1999 @@ -0,0 +1,299 @@ +/* + * USB HID boot protocol mouse support based on MS BusMouse driver, psaux + * driver, and Linus's skeleton USB mouse driver + * + * Brad Keryan 4/3/1999 + * + * version 0.02: Hmm, the mouse seems drunk because I'm queueing the events. + * This is wrong: when an application (like X or gpm) reads the mouse device, + * it wants to find out the mouse's current position, not its recent history. + * The button thing turned out to be UHCI not flipping data toggle, so half the + * packets were thrown out. + * + * version 0.01: Switched over to busmouse protocol, and changed the minor + * number to 32 (same as uusbd's hidbp driver). Buttons work more sanely now, + * but it still doesn't generate button events unless you move the mouse. + * + * version 0.0: Driver emulates a PS/2 mouse, stealing /dev/psaux (sorry, I + * know that's not very nice). Moving in the X and Y axes works. Buttons don't + * work right yet: X sees a lot of MotionNotify/ButtonPress/ButtonRelease + * combos when you hold down a button and drag the mouse around. Probably has + * some additional bugs on an SMP machine. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "usb.h" + +#define USB_MOUSE_MINOR 32 + +struct mouse_state { + unsigned char buttons; /* current button state */ + long dx; /* dx, dy, dz are change since last read */ + long dy; + long dz; + int present; /* this mouse is plugged in */ + int active; /* someone is has this mouse's device open */ + int ready; /* the mouse has changed state since the last read */ + struct wait_queue *wait; /* for polling */ + struct fasync_struct *fasync; + /* later, add a list here to support multiple mice */ + /* but we will also need a list of file pointers to identify it */ +}; + +static struct mouse_state static_mouse_state; + +spinlock_t usb_mouse_lock = SPIN_LOCK_UNLOCKED; + +static int mouse_irq(int state, void *__buffer, void *dev_id) +{ + signed char *data = __buffer; + /* finding the mouse is easy when there's only one */ + struct mouse_state *mouse = &static_mouse_state; + + /* if a mouse moves with no one listening, do we care? no */ + if(!mouse->active) + return 1; + + /* if the USB mouse sends an interrupt, then something noteworthy + must have happened */ + mouse->buttons = data[0] & 0x07; + mouse->dx += data[1]; /* data[] is signed, so this works */ + mouse->dy -= data[2]; /* y-axis is reversed */ + mouse->dz += data[3]; + mouse->ready = 1; + + add_mouse_randomness((mouse->buttons << 24) + (mouse->dz << 16 ) + + (mouse->dy << 8) + mouse->dx); + + wake_up_interruptible(&mouse->wait); + if (mouse->fasync) + kill_fasync(mouse->fasync, SIGIO); + + return 1; +} + +static int fasync_mouse(int fd, struct file *filp, int on) +{ + int retval; + struct mouse_state *mouse = &static_mouse_state; + + retval = fasync_helper(fd, filp, on, &mouse->fasync); + if (retval < 0) + return retval; + return 0; +} + +static int release_mouse(struct inode * inode, struct file * file) +{ + struct mouse_state *mouse = &static_mouse_state; + + fasync_mouse(-1, file, 0); + if (--mouse->active) + return 0; + return 0; +} + +static int open_mouse(struct inode * inode, struct file * file) +{ + struct mouse_state *mouse = &static_mouse_state; + + if (!mouse->present) + return -EINVAL; + if (mouse->active++) + return 0; + /* flush state */ + mouse->buttons = mouse->dx = mouse->dy = mouse->dz = 0; + return 0; +} + +static ssize_t write_mouse(struct file * file, + const char * buffer, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +/* + * Look like a PS/2 mouse, please.. + * + * The PS/2 protocol is fairly strange, but + * oh, well, it's at least common.. + */ +static ssize_t read_mouse(struct file * file, char * buffer, size_t count, loff_t *ppos) +{ + int retval = 0; + static int state = 0; + struct mouse_state *mouse = &static_mouse_state; + + if (count) { + mouse->ready = 0; + switch (state) { + case 0: { /* buttons and sign */ + int buttons = mouse->buttons; + mouse->buttons = 0; + if (mouse->dx < 0) + buttons |= 0x10; + if (mouse->dy < 0) + buttons |= 0x20; + put_user(buttons, buffer); + buffer++; + retval++; + state = 1; + if (!--count) + break; + } + case 1: { /* dx */ + int dx = mouse->dx; + mouse->dx = 0; + put_user(dx, buffer); + buffer++; + retval++; + state = 2; + if (!--count) + break; + } + case 2: { /* dy */ + int dy = mouse->dy; + mouse->dy = 0; + put_user(dy, buffer); + buffer++; + retval++; + state = 0; + } + break; + } + } + return retval; +} + +static unsigned int mouse_poll(struct file *file, poll_table * wait) +{ + struct mouse_state *mouse = &static_mouse_state; + + poll_wait(file, &mouse->wait, wait); + if (mouse->ready) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations usb_mouse_fops = { + NULL, /* mouse_seek */ + read_mouse, + write_mouse, + NULL, /* mouse_readdir */ + mouse_poll, /* mouse_poll */ + NULL, /* mouse_ioctl */ + NULL, /* mouse_mmap */ + open_mouse, + NULL, /* flush */ + release_mouse, + NULL, + fasync_mouse, +}; + +static struct miscdevice usb_mouse = { + USB_MOUSE_MINOR, "USB mouse", &usb_mouse_fops +}; + +static int mouse_probe(struct usb_device *dev) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct mouse_state *mouse = &static_mouse_state; + + /* We don't handle multi-config mice */ + if (dev->descriptor.bNumConfigurations != 1) + return -1; + + /* We don't handle multi-interface mice */ + if (dev->config[0].bNumInterfaces != 1) + return -1; + + /* Is it a mouse interface? */ + interface = &dev->config[0].interface[0]; + if (interface->bInterfaceClass != 3) + return -1; + if (interface->bInterfaceSubClass != 1) + return -1; + if (interface->bInterfaceProtocol != 2) + return -1; + + /* Multiple endpoints? What kind of mutant ninja-mouse is this? */ + if (interface->bNumEndpoints != 1) + return -1; + + endpoint = &interface->endpoint[0]; + + /* Output endpoint? Curiousier and curiousier.. */ + if (!(endpoint->bEndpointAddress & 0x80)) + return -1; + + /* If it's not an interrupt endpoint, we'd better punt! */ + if ((endpoint->bmAttributes & 3) != 3) + return -1; + + printk("USB mouse found\n"); + + usb_set_configuration(dev, dev->config[0].bConfigurationValue); + + usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), mouse_irq, endpoint->bInterval, NULL); + + mouse->present = 1; + return 0; +} + +static void mouse_disconnect(struct usb_device *dev) +{ + struct mouse_state *mouse = &static_mouse_state; + + /* this might need work */ + mouse->present = 0; +} + +static struct usb_driver mouse_driver = { + "mouse", + mouse_probe, + mouse_disconnect, + { NULL, NULL } +}; + +int usb_mouse_init(void) +{ + struct mouse_state *mouse = &static_mouse_state; + + misc_register(&usb_mouse); + + mouse->present = mouse->active = 0; + mouse->wait = NULL; + mouse->fasync = NULL; + + usb_register(&mouse_driver); + printk(KERN_INFO "USB HID boot protocol mouse registered.\n"); + return 0; +} + +#if 0 + +int init_module(void) +{ + return usb_mouse_init(); +} + +void cleanup_module(void) +{ + /* this, too, probably needs work */ + usb_deregister(&mouse_driver); + misc_deregister(&usb_mouse); +} + +#endif diff -u --recursive --new-file v2.2.6/linux/drivers/usb/ohci-debug.c linux/drivers/usb/ohci-debug.c --- v2.2.6/linux/drivers/usb/ohci-debug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/ohci-debug.c Mon Apr 26 12:52:33 1999 @@ -0,0 +1,139 @@ +/* + * OHCI debugging code. It's gross. + * + * (C) Copyright 1999 Gregory P. Smith + */ + +#include +#include + +#include "ohci.h" + +void show_ohci_status(struct ohci *ohci) +{ + struct ohci_regs regs; + int i; + + regs.revision = readl(ohci->regs->revision); + regs.control = readl(ohci->regs->control); + regs.cmdstatus = readl(ohci->regs->cmdstatus); + regs.intrstatus = readl(ohci->regs->intrstatus); + regs.intrenable = readl(ohci->regs->intrenable); + regs.intrdisable = readl(ohci->regs->intrdisable); + regs.hcca = readl(ohci->regs->hcca); + regs.ed_periodcurrent = readl(ohci->regs->ed_periodcurrent); + regs.ed_controlhead = readl(ohci->regs->ed_controlhead); + regs.ed_bulkhead = readl(ohci->regs->ed_bulkhead); + regs.ed_bulkcurrent = readl(ohci->regs->ed_bulkcurrent); + regs.current_donehead = readl(ohci->regs->current_donehead); + regs.fminterval = readl(ohci->regs->fminterval); + regs.fmremaining = readl(ohci->regs->fmremaining); + regs.fmnumber = readl(ohci->regs->fmnumber); + regs.periodicstart = readl(ohci->regs->periodicstart); + regs.lsthresh = readl(ohci->regs->lsthresh); + regs.roothub.a = readl(ohci->regs->roothub.a); + regs.roothub.b = readl(ohci->regs->roothub.b); + regs.roothub.status = readl(ohci->regs->roothub.status); + for (i=0; iregs->roothub.portstatus[i]); + + printk(" ohci revision = 0x%x\n", regs.revision); + printk(" ohci control = 0x%x\n", regs.control); + printk(" ohci cmdstatus = 0x%x\n", regs.cmdstatus); + printk(" ohci intrstatus = 0x%x\n", regs.intrstatus); + printk(" ohci roothub.a = 0x%x\n", regs.roothub.a); + printk(" ohci roothub.b = 0x%x\n", regs.roothub.b); + printk(" ohci root status = 0x%x\n", regs.roothub.status); +} /* show_ohci_status() */ + + +static void show_ohci_ed(struct ohci_ed *ed) +{ + int stat = ed->status; + int skip = (stat & OHCI_ED_SKIP); + int mps = (stat & OHCI_ED_MPS) >> 16; + int isoc = (stat & OHCI_ED_F_ISOC); + int low_speed = (stat & OHCI_ED_S_LOW); + int dir = (stat & OHCI_ED_D); + int endnum = (stat & OHCI_ED_EN) >> 7; + int funcaddr = (stat & OHCI_ED_FA); + int halted = (ed->head_td & 1); + int toggle = (ed->head_td & 2) >> 1; + + printk(" ohci ED:\n"); + printk(" status = 0x%x\n", stat); + printk(" %sMPS %d%s%s%s%s tc%d e%d fa%d\n", + skip ? "Skip " : "", + mps, + isoc ? "Isoc. " : "", + low_speed ? "LowSpd " : "", + (dir == OHCI_ED_D_IN) ? "Input " : + (dir == OHCI_ED_D_OUT) ? "Output " : "", + halted ? "Halted " : "", + toggle, + endnum, + funcaddr); + printk(" tail_td = 0x%x\n", ed->tail_td); + printk(" head_td = 0x%x\n", ed->head_td); + printk(" next_ed = 0x%x\n", ed->next_ed); +} /* show_ohci_ed() */ + + +static void show_ohci_td(struct ohci_td *td) +{ + int td_round = td->info & OHCI_TD_ROUND; + int td_dir = td->info & OHCI_TD_D; + int td_int_delay = td->info & OHCI_TD_IOC_DELAY; + int td_toggle = td->info & OHCI_TD_DT; + int td_errcnt = td_errorcount(td->info); + int td_cc = td->info & OHCI_TD_CC; + + printk(" ohci TD hardware fields:\n"); + printk(" info = 0x%x\n", td->info); + printk(" %s%s%s%d%s%s%d%s%d\n", + td_round ? "Rounding " : "", + (td_dir == OHCI_TD_D_IN) ? "Input " : + (td_dir == OHCI_TD_D_OUT) ? "Output " : + (td_dir == OHCI_TD_D_SETUP) ? "Setup " : "", + "IntDelay ", td_int_delay >> 21, + td_toggle ? "Data1 " : "Data0 ", + "ErrorCnt ", td_errcnt, + "ComplCode ", td_cc); + printk(" %sAccessed, %sActive\n", + td_cc_accessed(td->info) ? "" : "Not ", + td_active(td->info) ? "" : "Not "); + + printk(" cur_buf = 0x%x\n", td->cur_buf); + printk(" next_td = 0x%x\n", td->next_td); + printk(" buf_end = 0x%x\n", td->buf_end); + printk(" ohci TD driver fields:\n"); + printk(" data = %p\n", td->data); + printk(" dev_id = %p\n", td->dev_id); + printk(" ed_bus = %x\n", td->ed_bus); +} /* show_ohci_td() */ + + +void show_ohci_device(struct ohci_device *dev) +{ + int idx; + printk(" ohci_device usb = %p\n", dev->usb); + printk(" ohci_device ohci = %p\n", dev->ohci); + printk(" ohci_device ohci_hcca = %p\n", dev->hcca); + for (idx=0; idx<8 /*NUM_EDS*/; ++idx) { + printk(" [ed num %d] ", idx); + show_ohci_ed(&dev->ed[idx]); + } + for (idx=0; idx<8 /*NUM_TDS*/; ++idx) { + printk(" [td num %d] ", idx); + show_ohci_td(&dev->td[idx]); + } + printk(" ohci_device data\n "); + for (idx=0; idx<4; ++idx) { + printk(" %08lx", dev->data[idx]); + } + printk("\n"); +} /* show_ohci_device() */ + + +/* vim:sw=8 + */ diff -u --recursive --new-file v2.2.6/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c --- v2.2.6/linux/drivers/usb/ohci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/ohci.c Mon Apr 26 12:57:22 1999 @@ -0,0 +1,1040 @@ +/* + * Open Host Controller Interface driver for USB. + * + * (C) Copyright 1999 Gregory P. Smith + * + * This is the "other" host controller interface for USB. You will + * find this on many non-Intel based motherboards, and of course the + * Mac. As Linus hacked his UHCI driver together first, I modeled + * this after his.. (it should be obvious) + * + * From the programming standpoint the OHCI interface seems a little + * prettier and potentially less CPU intensive. This remains to be + * proven. In reality, I don't believe it'll make one darn bit of + * difference. USB v1.1 is a slow bus by today's standards. + * + * OHCI hardware takes care of most of the scheduling of different + * transfer types with the correct prioritization for us. + * + * To get started in USB, I used the "Universal Serial Bus System + * Architecture" book by Mindshare, Inc. It was a reasonable introduction + * and overview of USB and the two dominant host controller interfaces + * however you're better off just reading the real specs available + * from www.usb.org as you'll need them to get enough detailt to + * actually implement a HCD. The book has many typos and omissions + * Beware, the specs are the victim of a committee. + * + * This code was written with Guinness on the brain, xsnow on the desktop + * and Orbital, Orb, Enya & Massive Attack on the CD player. What a life! ;) + * + * No filesystems were harmed in the development of this code. + * + * $Id: ohci.c,v 1.11 1999/04/25 00:18:52 greg Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ohci.h" +#include "inits.h" + +#ifdef CONFIG_APM +#include +static int handle_apm_event(apm_event_t event); +static int apm_resume = 0; +#endif + +static struct wait_queue *ohci_configure = NULL; + + +static int ohci_td_result(struct ohci_device *dev, struct ohci_td *td) +{ + unsigned int status; + + status = td->info & OHCI_TD_CC; + + /* TODO Debugging code for TD failures goes here */ + + return status; +} + + +static spinlock_t ohci_edtd_lock = SPIN_LOCK_UNLOCKED; + +/* + * Add a TD to the end of the TD list on a given ED. td->next_td is + * assumed to be set correctly for the situation of no TDs already + * being on the list (ie: pointing to NULL). + */ +static void ohci_add_td_to_ed(struct ohci_td *td, struct ohci_ed *ed) +{ + struct ohci_td *tail = bus_to_virt(ed->tail_td); + struct ohci_td *head = bus_to_virt(ed->head_td); + unsigned long flags; + + spin_lock_irqsave(&ohci_edtd_lock, flags); + + if (tail == head) { /* empty list, put it on the head */ + head = (struct ohci_td *) virt_to_bus(td); + tail = 0; + } else { + if (!tail) { /* no tail, single element list */ + td->next_td = head->next_td; + head->next_td = virt_to_bus(td); + tail = (struct ohci_td *) virt_to_bus(td); + } else { /* append to the list */ + td->next_td = tail->next_td; + tail->next_td = virt_to_bus(td); + tail = (struct ohci_td *) virt_to_bus(td); + } + } + /* save the reverse link */ + td->ed_bus = virt_to_bus(ed); + + spin_unlock_irqrestore(&ohci_edtd_lock, flags); +} /* ohci_add_td_to_ed() */ + + +/* + * Remove a TD from the given EDs TD list + */ +static void ohci_remove_td_from_ed(struct ohci_td *td, struct ohci_ed *ed) +{ + struct ohci_td *head = bus_to_virt(ed->head_td); + struct ohci_td *tmp_td; + unsigned long flags; + + spin_lock_irqsave(&ohci_edtd_lock, flags); + + /* set the "skip me bit" in this ED */ + writel_set(OHCI_ED_SKIP, ed->status); + + /* XXX Assuming this list will never be circular */ + + if (td == head) { + /* unlink this TD; it was at the beginning */ + ed->head_td = head->next_td; + } + + tmp_td = head; + head = (struct ohci_td *) ed->head_td; + + while (head != NULL) { + + if (td == head) { + /* unlink this TD from the middle or end */ + tmp_td->next_td = head->next_td; + } + + tmp_td = head; + head = bus_to_virt(head->next_td); + } + + td->next_td = virt_to_bus(NULL); /* remove links to ED list */ + + /* XXX mark this TD for possible cleanup? */ + + /* unset the "skip me bit" in this ED */ + writel_mask(~(__u32)OHCI_ED_SKIP, ed->status); + + spin_unlock_irqrestore(&ohci_edtd_lock, flags); +} /* ohci_remove_td_from_ed() */ + + +/* + * Get a pointer (virtual) to an available TD from the given device's + * pool. + * + * Return NULL if none are left. + */ +static struct ohci_td *ohci_get_free_td(struct ohci_device *dev) +{ + int idx; + + for (idx=0; idx < NUM_TDS; idx++) { + if (td_done(dev->td[idx].info)) { + /* XXX should this also zero out the structure? */ + /* mark all new TDs as unaccessed */ + dev->td[idx].info = OHCI_TD_CC_NEW; + return &dev->td[idx]; + } + } + + return NULL; +} /* ohci_get_free_td() */ + + +/********************************** + * OHCI interrupt list operations * + **********************************/ +static spinlock_t irqlist_lock = SPIN_LOCK_UNLOCKED; + +static void ohci_add_irq_list(struct ohci *ohci, struct ohci_td *td, usb_device_irq completed, void *dev_id) +{ + unsigned long flags; + + /* save the irq in our private portion of the TD */ + td->completed = completed; + td->dev_id = dev_id; + + spin_lock_irqsave(&irqlist_lock, flags); + list_add(&td->irq_list, &ohci->interrupt_list); + spin_unlock_irqrestore(&irqlist_lock, flags); +} /* ohci_add_irq_list() */ + +static void ohci_remove_irq_list(struct ohci_td *td) +{ + unsigned long flags; + + spin_lock_irqsave(&irqlist_lock, flags); + list_del(&td->irq_list); + spin_unlock_irqrestore(&irqlist_lock, flags); +} /* ohci_remove_irq_list() */ + +/* + * Request an interrupt handler for one "pipe" of a USB device. + * (this function is pretty minimal right now) + * + * At the moment this is only good for input interrupts. (ie: for a + * mouse) + * + * period is desired polling interval in ms. The closest, shorter + * match will be used. Powers of two from 1-32 are supported by OHCI. + */ +static int ohci_request_irq(struct usb_device *usb, unsigned int pipe, + usb_device_irq handler, int period, void *dev_id) +{ + struct ohci_device *dev = usb_to_ohci(usb); + struct ohci_td *td = dev->td; /* */ + struct ohci_ed *interrupt_ed; /* endpoint descriptor for this irq */ + + /* + * Pick a good frequency endpoint based on the requested period + */ + interrupt_ed = &dev->ohci->root_hub->ed[ms_to_ed_int(period)]; + + /* + * Set the max packet size, device speed, endpoint number, usb + * device number (function address), and type of TD. + * + * FIXME: Isochronous transfers need a pool of special 32 byte + * TDs (32 byte aligned) in order to be supported. + */ + interrupt_ed->status = \ + ed_set_maxpacket(usb_maxpacket(pipe)) | + ed_set_speed(usb_pipeslow(pipe)) | + usb_pipe_endpdev(pipe) | + OHCI_ED_F_NORM; + + /* + * Set the not accessed condition code, allow odd sized data, + * and set the data transfer direction. + */ + td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | + td_set_dir_out(usb_pipeout(pipe)); + + /* point it to our data buffer */ + td->cur_buf = virt_to_bus(dev->data); + + /* FIXME: we're only using 1 TD right now! */ + td->next_td = virt_to_bus(&td); + + /* + * FIXME: be aware that OHCI won't advance out of the 4kb + * page cur_buf started in. It'll wrap around to the start + * of the page... annoying or useful? you decide. + * + * A pointer to the last *byte* in the buffer (ergh.. we get + * to work around C's pointer arithmatic here with a typecast) + */ + td->buf_end = virt_to_bus(((u8*)(dev->data + DATA_BUF_LEN)) - 1); + + /* does this make sense for ohci?.. time to think.. */ + ohci_add_irq_list(dev->ohci, td, handler, dev_id); + wmb(); /* found in asm/system.h; scary concept... */ + ohci_add_td_to_ed(td, interrupt_ed); + + return 0; +} /* ohci_request_irq() */ + +/* + * Control thread operations: + */ +static struct wait_queue *control_wakeup; + +static int ohci_control_completed(int stats, void *buffer, void *dev_id) +{ + wake_up(&control_wakeup); + return 0; +} /* ohci_control_completed() */ + + +/* + * Run a control transaction from the root hub's control endpoint. + * The passed in TD is the control transfer's Status TD. + */ +static int ohci_run_control(struct ohci_device *dev, struct ohci_td *status_td) +{ + struct wait_queue wait = { current, NULL }; + struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL]; + + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&control_wakeup, &wait); + + ohci_add_irq_list(dev->ohci, status_td, ohci_control_completed, NULL); + ohci_add_td_to_ed(status_td, control_ed); + + /* FIXME? isn't this a little gross */ + schedule_timeout(HZ/10); + + ohci_remove_irq_list(status_td); + ohci_remove_td_from_ed(status_td, control_ed); + + return ohci_td_result(dev, status_td); +} /* ohci_run_control() */ + +/* + * Send or receive a control message on a "pipe" + * + * A control message contains: + * - The command itself + * - An optional data phase + * - Status complete phase + * + * The data phase can be an arbitrary number of TD's. Currently since + * we use statically allocated TDs if too many come in we'll just + * start tossing them and printk() some warning goo... Most control + * messages won't have much data anyways. + */ +static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, void *cmd, void *data, int len) +{ + struct ohci_device *dev = usb_to_ohci(usb); + /* + * ideally dev->ed should be linked into the root hub's + * control_ed list and used instead of just using it directly. + * This could present a problem as is with more than one + * device. (but who wants to use a keyboard AND a mouse + * anyways? ;) + */ + struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL]; + struct ohci_td *control_td; + struct ohci_td *data_td; + struct ohci_td *last_td; + __u32 data_td_info; + + /* + * Set the max packet size, device speed, endpoint number, usb + * device number (function address), and type of TD. + * + */ + control_ed->status = \ + ed_set_maxpacket(usb_maxpacket(pipe)) | + ed_set_speed(usb_pipeslow(pipe)) | + usb_pipe_endpdev(pipe) | + OHCI_ED_F_NORM; + + /* + * Build the control TD + */ + + /* get a TD to send this control message with */ + control_td = ohci_get_free_td(dev); + /* TODO check for NULL */ + + /* + * Set the not accessed condition code, allow odd sized data, + * and set the data transfer type to SETUP. Setup DATA always + * uses a DATA0 packet. + */ + control_td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | + OHCI_TD_D_SETUP | OHCI_TD_IOC_OFF | td_force_toggle(0); + + /* point it to the command */ + control_td->cur_buf = virt_to_bus(cmd); + + /* link to a free TD for the control data input */ + data_td = ohci_get_free_td(dev); /* TODO check for NULL */ + control_td->next_td = virt_to_bus(data_td); + + /* + * Build the DATA TDs + */ + + data_td_info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | OHCI_TD_IOC_OFF | + td_set_dir_out(usb_pipeout(pipe)); + + while (len > 0) { + int pktsize = len; + struct ohci_td *tmp_td; + + if (pktsize > usb_maxpacket(pipe)) + pktsize = usb_maxpacket(pipe); + + /* set the data transaction type */ + data_td->info = data_td_info; + /* point to the current spot in the data buffer */ + data_td->cur_buf = virt_to_bus(data); + /* point to the end of this data */ + data_td->buf_end = virt_to_bus(data+pktsize-1); + + /* allocate the next TD */ + tmp_td = ohci_get_free_td(dev); /* TODO check for NULL */ + data_td->next_td = virt_to_bus(tmp_td); + data_td = tmp_td; + + /* move on.. */ + data += pktsize; + len -= pktsize; + } + + /* point it at the newly allocated TD from above */ + last_td = data_td; + + /* The control status packet always uses a DATA1 */ + last_td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | td_force_toggle(1); + last_td->next_td = 0; /* end of TDs */ + last_td->cur_buf = 0; /* no data in this packet */ + last_td->buf_end = 0; + + /* + * Start the control transaction.. give it the last TD so the + * result can be returned. + */ + return ohci_run_control(dev, last_td); +} /* ohci_control_msg() */ + + +static struct usb_device *ohci_usb_allocate(struct usb_device *parent) +{ + struct usb_device *usb_dev; + struct ohci_device *dev; + + usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL); + if (!usb_dev) + return NULL; + + memset(usb_dev, 0, sizeof(*usb_dev)); + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + kfree(usb_dev); + return NULL; + } + + /* Initialize "dev" */ + memset(dev, 0, sizeof(*dev)); + + usb_dev->hcpriv = dev; + dev->usb = usb_dev; + + usb_dev->parent = parent; + + if (parent) { + usb_dev->bus = parent->bus; + dev->ohci = usb_to_ohci(parent)->ohci; + } + + return usb_dev; +} + +static int ohci_usb_deallocate(struct usb_device *usb_dev) +{ + kfree(usb_to_ohci(usb_dev)); + kfree(usb_dev); + return 0; +} + +/* + * functions for the generic USB driver + */ +struct usb_operations ohci_device_operations = { + ohci_usb_allocate, + ohci_usb_deallocate, + ohci_control_msg, + ohci_request_irq, +}; + +/* + * Reset an OHCI controller + */ +static void reset_hc(struct ohci *ohci) +{ + writel((1<<31), &ohci->regs->intrdisable); /* Disable HC interrupts */ + writel(1, &ohci->regs->cmdstatus); /* HC Reset */ + writel_mask(0x3f, &ohci->regs->control); /* move to UsbReset state */ +} /* reset_hc() */ + + +/* + * Reset and start an OHCI controller + */ +static void start_hc(struct ohci *ohci) +{ + int timeout = 1000; /* used to prevent an infinite loop. */ + + reset_hc(ohci); + + while ((readl(&ohci->regs->control) & 0xc0) == 0) { + if (!--timeout) { + printk("USB HC Reset timed out!\n"); + break; + } + } + + /* Choose the interrupts we care about */ + writel( OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_SF | + OHCI_INTR_WDH | OHCI_INTR_SO | OHCI_INTR_UE | + OHCI_INTR_FNO, + &ohci->regs->intrenable); + + /* Enter the USB Operational state & start the frames a flowing.. */ + writel_set(OHCI_USB_OPER, &ohci->regs->control); + +} /* start_hc() */ + + +/* + * Reset a root hub port + */ +static void ohci_reset_port(struct ohci *ohci, unsigned int port) +{ + short ms; + int status; + + /* Don't allow overflows. */ + if (port >= MAX_ROOT_PORTS) { + printk("Bad port # passed to ohci_reset_port\n"); + port = MAX_ROOT_PORTS-1; + } + + writel(PORT_PRS, &ohci->regs->roothub.portstatus[port]); /* Reset */ + + /* + * Get the time required for a root hub port to reset and wait + * it out (adding 1ms for good measure). + */ + ms = (readl(&ohci->regs->roothub.a) >> 24) * 2 + 1; + wait_ms(ms); + + /* check port status to see that the reset completed */ + status = readl(&ohci->regs->roothub.portstatus[port]); + if (status & PORT_PRS) { + /* reset failed, try harder? */ + printk("usb-ohci: port %d reset failed, retrying\n", port); + writel(PORT_PRS, &ohci->regs->roothub.portstatus[port]); + wait_ms(50); + } + + /* TODO we might need to re-enable the port here or is that + * done elsewhere? */ + +} /* ohci_reset_port */ + + +/* + * This gets called if the connect status on the root hub changes. + */ +static void ohci_connect_change(struct ohci * ohci, int port) +{ + struct usb_device *usb_dev; + struct ohci_device *dev; + /* memory I/O address of the port status register */ + void *portaddr = &ohci->regs->roothub.portstatus[port]; + int portstatus; + + /* + * Because of the status change we have to forget + * everything we think we know about the device + * on this root hub port. It may have changed. + */ + usb_disconnect(ohci->root_hub->usb->children + port); + + portstatus = readl(portaddr); + + /* disable the port if nothing is connected */ + if (!(portstatus & PORT_CCS)) { + writel(PORT_CCS, portaddr); + return; + } + + /* + * Allocate a device for the new thingy that's been attached + */ + usb_dev = ohci_usb_allocate(ohci->root_hub->usb); + dev = usb_dev->hcpriv; + + dev->ohci = ohci; + + usb_connect(dev->usb); + + /* link it into the bus's device tree */ + ohci->root_hub->usb->children[port] = usb_dev; + + wait_ms(200); /* wait for powerup; XXX is this needed? */ + ohci_reset_port(ohci, port); + + /* Get information on speed by using LSD */ + usb_dev->slow = readl(portaddr) & PORT_LSDA ? 1 : 0; + + /* + * Do generic USB device tree processing on the new device. + */ + usb_new_device(usb_dev); +} /* ohci_connect_change() */ + + +/* + * This gets called when the root hub configuration + * has changed. Just go through each port, seeing if + * there is something interesting happening. + */ +static void ohci_check_configuration(struct ohci *ohci) +{ + int num = 0; + int maxport = readl(&ohci->regs->roothub) & 0xff; + + do { + if (readl(ohci->regs->roothub.portstatus[num]) & PORT_CSC) + ohci_connect_change(ohci, num); + } while (++num < maxport); +} /* ohci_check_configuration() */ + + +/* + * Get annoyed at the controller for bothering us. + */ +static void ohci_interrupt(int irq, void *__ohci, struct pt_regs *r) +{ + struct ohci *ohci = __ohci; + struct ohci_regs *regs = ohci->regs; + struct ohci_hcca *hcca = ohci->root_hub->hcca; + __u32 donehead = hcca->donehead; + + /* + * Check the interrupt status register if needed + */ + if (!donehead || (donehead & 1)) { + __u32 intrstatus = readl(®s->intrstatus); + + /* + * XXX eek! printk's in an interrupt handler. shoot me! + */ + if (intrstatus & OHCI_INTR_SO) { + printk(KERN_DEBUG "usb-ohci: scheduling overrun\n"); + } + if (intrstatus & OHCI_INTR_RD) { + printk(KERN_DEBUG "usb-ohci: resume detected\n"); + } + if (intrstatus & OHCI_INTR_UE) { + printk(KERN_DEBUG "usb-ohci: unrecoverable error\n"); + } + if (intrstatus & OHCI_INTR_OC) { + printk(KERN_DEBUG "usb-ohci: ownership change?\n"); + } + + if (intrstatus & OHCI_INTR_RHSC) { + /* TODO Process events on the root hub */ + } + } + + /* + * Process the done list + */ + if (donehead &= ~0x1) { + /* + * TODO See which TD's completed.. + */ + } + + /* Re-enable done queue interrupts and reset the donehead */ + hcca->donehead = 0; + writel(OHCI_INTR_WDH, ®s->intrenable); + +} /* ohci_interrupt() */ + + +/* + * Allocate the resources required for running an OHCI controller. + * Host controller interrupts must not be running while calling this + * function or the penguins will get angry. + * + * The mem_base parameter must be the usable -virtual- address of the + * host controller's memory mapped I/O registers. + */ +static struct ohci *alloc_ohci(void* mem_base) +{ + int i; + struct ohci *ohci; + struct usb_bus *bus; + struct ohci_device *dev; + struct usb_device *usb; + + ohci = kmalloc(sizeof(*ohci), GFP_KERNEL); + if (!ohci) + return NULL; + + memset(ohci, 0, sizeof(*ohci)); + + ohci->irq = -1; + ohci->regs = mem_base; + INIT_LIST_HEAD(&ohci->interrupt_list); + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return NULL; + + memset(bus, 0, sizeof(*bus)); + + ohci->bus = bus; + bus->hcpriv = ohci; + bus->op = &ohci_device_operations; + + /* + * Here we allocate our own root hub and TDs as well as the + * OHCI host controller communications area. The HCCA is just + * a nice pool of memory with pointers to endpoint descriptors + * for the different interrupts. + */ + usb = ohci_usb_allocate(NULL); + if (!usb) + return NULL; + + dev = ohci->root_hub = usb_to_ohci(usb); + + usb->bus = bus; + + /* Initialize the root hub */ + memset(dev, 0, sizeof(*dev)); + dev->ohci = ohci; /* link back to the controller */ + + /* + * Allocate the Host Controller Communications Area + */ + dev->hcca = (struct ohci_hcca *) kmalloc(sizeof(*dev->hcca), GFP_KERNEL); + + /* Tell the controller where the HCCA is */ + writel(virt_to_bus(dev->hcca), &ohci->regs->hcca); + + /* Get the number of ports on the root hub */ + usb->maxchild = readl(&ohci->regs->roothub.a) & 0xff; + if (usb->maxchild > MAX_ROOT_PORTS) { + printk("usb-ohci: Limited to %d ports\n", MAX_ROOT_PORTS); + usb->maxchild = MAX_ROOT_PORTS; + } + if (usb->maxchild < 1) { + printk("usb-ohci: Less than one root hub port? Impossible!\n"); + usb->maxchild = 1; + } + printk("usb-ohci: %d root hub ports found\n", usb->maxchild); + + printk("alloc_ohci() controller\n"); + show_ohci_status(ohci); + printk("alloc_ohci() root_hub device\n"); + show_ohci_device(dev); + + /* + * Initialize the ED polling "tree" (for simplicity's sake in + * this driver many nodes in the tree will be identical) + */ + dev->ed[ED_INT_32].next_ed = virt_to_bus(&dev->ed[ED_INT_16]); + dev->ed[ED_INT_16].next_ed = virt_to_bus(&dev->ed[ED_INT_8]); + dev->ed[ED_INT_8].next_ed = virt_to_bus(&dev->ed[ED_INT_4]); + dev->ed[ED_INT_4].next_ed = virt_to_bus(&dev->ed[ED_INT_2]); + dev->ed[ED_INT_2].next_ed = virt_to_bus(&dev->ed[ED_INT_1]); + + /* + * Initialize the polling table to call interrupts at the + * intended intervals. + */ + for (i = 0; i < NUM_INTS; i++) { + if (i == 0) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_32]); + else if (i & 1) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_16]); + else if (i & 2) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_8]); + else if (i & 4) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_4]); + else if (i & 8) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_2]); + else if (i & 16) + dev->hcca->int_table[i] = + virt_to_bus(&dev->ed[ED_INT_1]); + } + + /* + * Tell the controller where the control and bulk lists are + */ + writel(virt_to_bus(&dev->ed[ED_CONTROL]), &ohci->regs->ed_controlhead); + writel(virt_to_bus(&dev->ed[ED_BULK]), &ohci->regs->ed_bulkhead); + + return ohci; +} /* alloc_ohci() */ + + +/* + * De-allocate all resoueces.. + */ +static void release_ohci(struct ohci *ohci) +{ + if (ohci->irq >= 0) { + free_irq(ohci->irq, ohci); + ohci->irq = -1; + } + + if (ohci->root_hub) { + /* ensure that HC is stopped before releasing the HCCA */ + writel(OHCI_USB_SUSPEND, &ohci->regs->control); + free_pages((unsigned int) ohci->root_hub->hcca, 1); + free_pages((unsigned int) ohci->root_hub, 1); + ohci->root_hub->hcca = NULL; + ohci->root_hub = NULL; + } + + /* unmap the IO address space */ + iounmap(ohci->regs); + + /* If the ohci itself were dynamic we'd free it here */ + +} /* release_ohci() */ + +/* + * USB OHCI control thread + */ +static int ohci_control_thread(void * __ohci) +{ + struct ohci *ohci = (struct ohci *)__ohci; + + /* + * I'm unfamiliar with the SMP kernel locking.. where should + * this be released? -greg + */ + lock_kernel(); + + /* + * This thread doesn't need any user-level access, + * so get rid of all of our resources.. + */ + printk("ohci_control_thread at %p\n", &ohci_control_thread); + exit_mm(current); + exit_files(current); + exit_fs(current); + + strcpy(current->comm, "ohci-control"); + + /* + * Damn the torpedoes, full speed ahead + */ + start_hc(ohci); + do { + interruptible_sleep_on(&ohci_configure); +#ifdef CONFIG_APM + if (apm_resume) { + apm_resume = 0; + start_hc(ohci); + continue; + } +#endif + ohci_check_configuration(ohci); + } while (!signal_pending(current)); + + reset_hc(ohci); + + release_ohci(ohci); + MOD_DEC_USE_COUNT; + return 0; +} /* ohci_control_thread() */ + + +#ifdef CONFIG_APM +static int handle_apm_event(apm_event_t event) +{ + static int down = 0; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + if (down) { + printk(KERN_DEBUG "usb-ohci: received extra suspend event\n"); + break; + } + down = 1; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + if (!down) { + printk(KERN_DEBUG "usb-ohci: received bogus resume event\n"); + break; + } + down = 0; + if (waitqueue_active(&ohci_configure)) { + apm_resume = 1; + wake_up(&ohci_configure); + } + break; + } + return 0; +} +#endif + +/* ... */ + +/* + * Increment the module usage count, start the control thread and + * return success if the controller is good. + */ +static int found_ohci(int irq, void* mem_base) +{ + int retval; + struct ohci *ohci; + + /* Allocate the running OHCI structures */ + ohci = alloc_ohci(mem_base); + if (!ohci) + return -ENOMEM; + + printk("usb-ohci: alloc_ohci() = %p\n", ohci); + + reset_hc(ohci); + + retval = -EBUSY; + if (request_irq(irq, ohci_interrupt, SA_SHIRQ, "usb-ohci", ohci) == 0) { + int pid; + + MOD_INC_USE_COUNT; + ohci->irq = irq; + + /* fork off the handler */ + pid = kernel_thread(ohci_control_thread, ohci, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (pid >= 0) + return 0; + + MOD_DEC_USE_COUNT; + retval = pid; + } + release_ohci(ohci); + return retval; +} /* found_ohci() */ + + +/* + * If this controller is for real, map the IO memory and proceed + */ +static int init_ohci(struct pci_dev *dev) +{ + unsigned int mem_base = dev->base_address[0]; + + printk("usb-ohci: mem_base is %p\n", (void*)mem_base); + + /* If its OHCI, its memory */ + if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) + return -ENODEV; + + /* Get the memory address and map it for IO */ + mem_base &= PCI_BASE_ADDRESS_MEM_MASK; + /* + * FIXME ioremap_nocache isn't implemented on all CPUs (such + * as the Alpha) [?] What should I use instead... + * + * The iounmap() is done on in release_ohci. + */ + mem_base = (unsigned int) ioremap_nocache(mem_base, 4096); + + if (!mem_base) { + printk("Error mapping OHCI memory\n"); + return -EFAULT; + } + + return found_ohci(dev->irq, (void *) mem_base); +} /* init_ohci() */ + + +#ifdef MODULE + +/* + * Clean up when unloading the module + */ +void cleanup_module(void) +{ +#ifdef CONFIG_APM + apm_unregister_callback(&handle_apm_event); +#endif +} + +#define ohci_init init_module + +#endif + + +/* TODO this should be named following Linux convention and go in pci.h */ +#define PCI_CLASS_SERIAL_USB_OHCI ((PCI_CLASS_SERIAL_USB << 8) | 0x0010) + +/* + * Search the PCI bus for an OHCI USB controller and set it up + * + * If anyone wants multiple controllers this will need to be + * updated.. Right now, it just picks the first one it finds. + */ +int ohci_init(void) +{ + int retval; + struct pci_dev *dev = NULL; + /*u8 type;*/ + + if (sizeof(struct ohci_device) > 4096) { + printk("usb-ohci: struct ohci_device to large\n"); + return -ENODEV; + } + + retval = -ENODEV; + for (;;) { + /* Find an OHCI USB controller */ + dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev); + if (!dev) + break; + + /* Verify that its OpenHCI by checking for MMIO */ + /* pci_read_config_byte(dev, PCI_CLASS_PROG, &type); + if (!type) + continue; */ + + /* Ok, set it up */ + retval = init_ohci(dev); + if (retval < 0) + continue; + + /* TODO check module params here to determine what to load */ + +/* usb_mouse_init(); */ +/* usb_kbd_init(); + hub_init(); */ +#ifdef CONFIG_APM + apm_register_callback(&handle_apm_event); +#endif + + return 0; /* no error */ + } + return retval; +} /* init_module() */ + +/* vim:sw=8 + */ diff -u --recursive --new-file v2.2.6/linux/drivers/usb/ohci.h linux/drivers/usb/ohci.h --- v2.2.6/linux/drivers/usb/ohci.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/ohci.h Mon Apr 26 12:51:57 1999 @@ -0,0 +1,301 @@ +#ifndef __LINUX_OHCI_H +#define __LINUX_OHCI_H + +/* + * Open Host Controller Interface data structures and defines. + * + * (C) Copyright 1999 Gregory P. Smith + * + * $Id: ohci.h,v 1.6 1999/04/24 22:50:06 greg Exp $ + */ + +#include +#include + +#include "usb.h" + +/* + * Each TD must be aligned on a 16-byte boundary. From the OHCI v1.0 spec + * it does not state that TDs must be contiguious in memory (due to the + * use of the next_td field). This gives us extra room at the end of a + * TD for our own driver specific data. + * + * This structure's size must be a multiple of 16 bytes. + */ +struct ohci_td { + /* OHCI Hardware fields */ + __u32 info; + __u32 cur_buf; /* Current Buffer Pointer */ + __u32 next_td; /* Next TD Pointer */ + __u32 buf_end; /* Memory Buffer End Pointer */ + + /* Driver specific fields */ + struct list_head irq_list; /* Active interrupt list */ + usb_device_irq completed; /* Completion handler routine */ + void *data; /* XXX ? */ + void *dev_id; /* XXX ? */ + __u32 ed_bus; /* bus address of original ED */ +} __attribute((aligned(32))); + +#define OHCI_TD_ROUND (1 << 18) /* buffer rounding bit */ +#define OHCI_TD_D (3 << 11) /* direction of xfer: */ +#define OHCI_TD_D_IN (2 << 11) +#define OHCI_TD_D_OUT (1 << 11) +#define OHCI_TD_D_SETUP (0) +#define td_set_dir_in(d) ((d) ? OHCI_TD_D_IN : OHCI_TD_D_OUT ) +#define td_set_dir_out(d) ((d) ? OHCI_TD_D_OUT : OHCI_TD_D_IN ) +#define OHCI_TD_IOC_DELAY (7 << 21) /* frame delay allowed before int. */ +#define OHCI_TD_IOC_OFF (OHCI_TD_IOC_DELAY) /* no interrupt on complete */ +#define OHCI_TD_DT (3 << 24) /* data toggle bits */ +#define td_force_toggle(b) (((b) | 2) << 24) +#define OHCI_TD_ERRCNT (3 << 26) /* error count */ +#define td_errorcount(td) (((td) >> 26) & 3) +#define OHCI_TD_CC (0xf << 28) /* condition code */ +#define OHCI_TD_CC_NEW (OHCI_TD_CC) /* set this on all unaccessed TDs! */ +#define td_cc_notaccessed(td) ((td >> 29) == 7) +#define td_cc_accessed(td) ((td >> 29) != 7) +#define td_cc_noerror(td) (((td) & OHCI_TD_CC) == 0) +#define td_active(td) (!td_cc_noerror((td)) && (td_errorcount((td)) < 3)) +#define td_done(td) (td_cc_noerror((td)) || (td_errorcount((td)) == 3)) + +/* + * The endpoint descriptors also requires 16-byte alignment + */ +struct ohci_ed { + /* OHCI hardware fields */ + __u32 status; + __u32 tail_td; /* TD Queue tail pointer */ + __u32 head_td; /* TD Queue head pointer */ + __u32 next_ed; /* Next ED */ +} __attribute((aligned(16))); + +#define OHCI_ED_SKIP (1 << 14) +#define OHCI_ED_MPS (0x7ff << 16) +/* FIXME: should cap at the USB max packet size [0x4ff] */ +#define ed_set_maxpacket(s) (((s) << 16) & OHCI_ED_MPS) +#define OHCI_ED_F_NORM (0) +#define OHCI_ED_F_ISOC (1 << 15) +#define ed_set_type_isoc(i) ((i) ? OHCI_ED_F_ISOC : OHCI_ED_F_NORM) +#define OHCI_ED_S_LOW (1 << 13) +#define OHCI_ED_S_HIGH (0) +#define ed_set_speed(s) ((s) ? OHCI_ED_S_LOW : OHCI_ED_S_HIGH) +#define OHCI_ED_D (3 << 11) +#define OHCI_ED_D_IN (2 << 11) +#define OHCI_ED_D_OUT (1 << 11) +#define ed_set_dir_in(d) ((d) ? OHCI_ED_D_IN : OHCI_ED_D_OUT) +#define ed_set_dir_out(d) ((d) ? OHCI_ED_D_OUT : OHCI_ED_D_IN) +#define OHCI_ED_EN (0xf << 7) +#define OHCI_ED_FA (0x7f) + + +/* NOTE: bits 27-31 of the status dword are reserved for the driver */ +/* + * We'll use this status flag for the non-predefined EDs to mark if + * they're in use or not. + * + * FIXME: unimplemented (needed?) + */ +#define ED_USED (1 << 31) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 donehead; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + +/* + * The TD entries here are pre-allocated as Linus did with his simple + * UHCI implementation. With the current state of this driver that + * shouldn't be a problem. However if someone ever connects 127 + * supported devices to this driver and tries to use them all at once: + * a) They're insane! + * b) They should code in dynamic allocation + */ +struct ohci; + +/* + * Warning: These constants must not be so large as to cause the + * ohci_device structure to exceed one 4096 byte page. Or "weird + * things will happen" as the alloc_ohci() function assumes that + * its less than one page. (FIXME) + */ +#define NUM_TDS 32 /* num of preallocated transfer descriptors */ +#define DATA_BUF_LEN 16 /* num of unsigned long's for the data buf */ + +/* + * For this "simple" driver we only support a single ED for each + * polling rate. + * + * Later on this driver should be extended to use a full tree of EDs + * so that there can be 32 different 32ms polling frames, etc. + * Individual devices shouldn't need as many as the root hub in that + * case; complicating how things are done at the moment. + * + * Bulk and Control transfers hang off of their own ED lists. + */ +#define NUM_EDS 16 /* num of preallocated endpoint descriptors */ + +#define ohci_to_usb(ohci) ((ohci)->usb) +#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) + +/* The usb_device must be first! */ +struct ohci_device { + struct usb_device *usb; + + struct ohci *ohci; + struct ohci_hcca *hcca; /* OHCI mem. mapped IO area */ + + struct ohci_ed ed[NUM_EDS]; /* Endpoint Descriptors */ + struct ohci_td td[NUM_TDS]; /* Transfer Descriptors */ + + unsigned long data[DATA_BUF_LEN]; +}; + +/* .... */ + +#define ED_INT_1 0 +#define ED_INT_2 1 +#define ED_INT_4 2 +#define ED_INT_8 3 +#define ED_INT_16 4 +#define ED_INT_32 5 +#define ED_CONTROL 6 +#define ED_BULK 7 +#define ED_ISO ED_INT_1 /* same as 1ms interrupt queue */ +#define ED_FIRST_AVAIL 8 /* first non-reserved ED */ + +/* + * Given a period p in ms, convert it to the closest endpoint + * interrupt frequency; rounding down. I'm sure many feel that this + * is a gross macro. Feel free to toss it for actual code. + */ +#define ms_to_ed_int(p) \ + ((p >= 32) ? ED_INT_32 : \ + ((p & 16) ? ED_INT_16 : \ + ((p & 8) ? ED_INT_8 : \ + ((p & 4) ? ED_INT_4 : \ + ((p & 2) ? ED_INT_2 : \ + ED_INT_1))))) /* hmm.. scheme or lisp anyone? */ + +/* + * This is the maximum number of root hub ports. I don't think we'll + * ever see more than two as that's the space available on an ATX + * motherboard's case, but it could happen. The OHCI spec allows for + * up to 15... (which is insane!) + * + * Although I suppose several "ports" could be connected directly to + * internal laptop devices such as a keyboard, mouse, camera and + * serial/parallel ports. hmm... That'd be neat. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 current_donehead; /* The driver should get this from the HCCA */ + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + +/* + * Read a MMIO register and re-write it after ANDing with (m) + */ +#define writel_mask(m, a) writel( (readl((__u32)(a))) & (__u32)(m), (__u32)(a) ) + +/* + * Read a MMIO register and re-write it after ORing with (b) + */ +#define writel_set(b, a) writel( (readl((__u32)(a))) | (__u32)(b), (__u32)(a) ) + + +#define PORT_CCS (1) /* port current connect status */ +#define PORT_PES (1 << 1) /* port enable status */ +#define PORT_PSS (1 << 2) /* port suspend status */ +#define PORT_POCI (1 << 3) /* port overcurrent indicator */ +#define PORT_PRS (1 << 4) /* port reset status */ +#define PORT_PPS (1 << 8) /* port power status */ +#define PORT_LSDA (1 << 9) /* port low speed dev. attached */ +#define PORT_CSC (1 << 16) /* port connect status change */ +#define PORT_PESC (1 << 17) /* port enable status change */ +#define PORT_PSSC (1 << 18) /* port suspend status change */ +#define PORT_OCIC (1 << 19) /* port over current indicator chg */ +#define PORT_PRSC (1 << 20) /* port reset status change */ + + +/* + * Interrupt register masks + */ +#define OHCI_INTR_SO (1) +#define OHCI_INTR_WDH (1 << 1) +#define OHCI_INTR_SF (1 << 2) +#define OHCI_INTR_RD (1 << 3) +#define OHCI_INTR_UE (1 << 4) +#define OHCI_INTR_FNO (1 << 5) +#define OHCI_INTR_RHSC (1 << 6) +#define OHCI_INTR_OC (1 << 30) +#define OHCI_INTR_MIE (1 << 31) + +/* + * Control register masks + */ +#define OHCI_USB_OPER (2 << 6) +#define OHCI_USB_SUSPEND (3 << 6) + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ +struct ohci { + int irq; + struct ohci_regs *regs; /* OHCI controller's memory */ + struct usb_bus *bus; + struct ohci_device *root_hub; /* Root hub & controller */ + struct list_head interrupt_list; /* List of interrupt active TDs for this OHCI */ +}; + +/* Debugging code */ +void show_ed(struct ohci_ed *ed); +void show_td(struct ohci_td *td); +void show_status(struct ohci *ohci); + +#endif +/* vim:sw=8 + */ diff -u --recursive --new-file v2.2.6/linux/drivers/usb/restart linux/drivers/usb/restart --- v2.2.6/linux/drivers/usb/restart Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/restart Fri Apr 16 15:22:40 1999 @@ -0,0 +1,35 @@ +#!/bin/sh + +ME=`basename $0` + +#UMOD=`lsmod | grep '^bp-mouse' | grep -v grep` +#if test "$UMOD"; then +# echo "$ME: removing bp-mouse.o" +# if ! rmmod bp-mouse; then +# echo "$ME: cannot remove bp-mouse.o" +# exit 1 +# fi +#fi + +UPID=`ps aux | grep uhci-control | grep -v grep | awk '{print $2}'` +if test "$UPID"; then + echo "$ME: killing $UPID" + kill $UPID +fi + +UMOD=`lsmod | grep '^usb-uhci' | grep -v grep` +if test "$UMOD"; then + echo "$ME: removing usb-uhci.o" + sleep 1 + if ! rmmod usb-uhci; then + echo "$ME: cannot remove usb-uhci.o" + exit 1 + fi +fi + +dmesg -c > /dev/null + +echo "$ME: starting usb-uhci.o" +insmod -m usb-uhci.o > usb-uhci.map +#echo "$ME: starting bp-mouse.o" +#insmod -m bp-mouse.o > bp-mouse.map diff -u --recursive --new-file v2.2.6/linux/drivers/usb/stopusb linux/drivers/usb/stopusb --- v2.2.6/linux/drivers/usb/stopusb Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/stopusb Wed Apr 21 02:42:11 1999 @@ -0,0 +1,8 @@ +#!/bin/sh + +killall uhci-control +killall khubd + +sleep 1 + +rmmod usb-uhci diff -u --recursive --new-file v2.2.6/linux/drivers/usb/uhci-debug.c linux/drivers/usb/uhci-debug.c --- v2.2.6/linux/drivers/usb/uhci-debug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/uhci-debug.c Mon Apr 26 12:22:58 1999 @@ -0,0 +1,168 @@ +/* + * UHCI-specific debugging code. Invaluable when something + * goes wrong, but don't get in my face. + * + * (C) Copyright 1999 Linus Torvalds + */ + +#include +#include + +#include "uhci.h" + +void show_td(struct uhci_td * td) +{ + printk("%08x ", td->link); + printk("%se%d %s%s%s%s%s%s%s%s%s%sLength=%x ", + ((td->status >> 29) & 1) ? "SPD " : "", + ((td->status >> 27) & 3), + ((td->status >> 26) & 1) ? "LS " : "", + ((td->status >> 25) & 1) ? "IOS " : "", + ((td->status >> 24) & 1) ? "IOC " : "", + ((td->status >> 23) & 1) ? "Active " : "", + ((td->status >> 22) & 1) ? "Stalled " : "", + ((td->status >> 21) & 1) ? "DataBufErr " : "", + ((td->status >> 20) & 1) ? "Babble " : "", + ((td->status >> 19) & 1) ? "NAK " : "", + ((td->status >> 18) & 1) ? "CRC/Timeo " : "", + ((td->status >> 17) & 1) ? "BitStuff " : "", + td->status & 0x7ff); + printk("MaxLen=%x %sEndPt=%x Dev=%x, PID=%x ", + td->info >> 21, + ((td->info >> 19) & 1) ? "DT " : "", + (td->info >> 15) & 15, + (td->info >> 8) & 127, + td->info & 0xff); + printk("(buf=%08x)\n", td->buffer); +} + +static void show_sc(int port, unsigned short status) +{ + printk(" stat%d = %04x %s%s%s%s%s%s%s%s\n", + port, + status, + (status & (1 << 12)) ? " PortSuspend" : "", + (status & (1 << 9)) ? " PortReset" : "", + (status & (1 << 8)) ? " LowSpeed" : "", + (status & 0x40) ? " ResumeDetect" : "", + (status & 0x08) ? " EnableChange" : "", + (status & 0x04) ? " PortEnabled" : "", + (status & 0x02) ? " ConnectChange" : "", + (status & 0x01) ? " PortConnected" : ""); +} + +void show_status(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + unsigned short usbcmd, usbstat, usbint, usbfrnum; + unsigned int flbaseadd; + unsigned char sof; + unsigned short portsc1, portsc2; + + usbcmd = inw(io_addr + 0); + usbstat = inw(io_addr + 2); + usbint = inw(io_addr + 4); + usbfrnum = inw(io_addr + 6); + flbaseadd = inl(io_addr + 8); + sof = inb(io_addr + 12); + portsc1 = inw(io_addr + 16); + portsc2 = inw(io_addr + 18); + + printk(" usbcmd = %04x %s%s%s%s%s%s%s%s\n", + usbcmd, + (usbcmd & 0x80) ? " Maxp64" : " Maxp32", + (usbcmd & 0x40) ? " CF" : "", + (usbcmd & 0x20) ? " SWDBG" : "", + (usbcmd & 0x10) ? " FGR" : "", + (usbcmd & 0x08) ? " EGSM" : "", + (usbcmd & 0x04) ? " GRESET" : "", + (usbcmd & 0x02) ? " HCRESET" : "", + (usbcmd & 0x01) ? " RS" : ""); + + printk(" usbstat = %04x %s%s%s%s%s%s\n", + usbstat, + (usbstat & 0x20) ? " HCHalted" : "", + (usbstat & 0x10) ? " HostControllerProcessError" : "", + (usbstat & 0x08) ? " HostSystemError" : "", + (usbstat & 0x04) ? " ResumeDetect" : "", + (usbstat & 0x02) ? " USBError" : "", + (usbstat & 0x01) ? " USBINT" : ""); + + printk(" usbint = %04x\n", usbint); + printk(" usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, 0xfff & (4*(unsigned int)usbfrnum)); + printk(" flbaseadd = %08x\n", flbaseadd); + printk(" sof = %02x\n", sof); + show_sc(1, portsc1); + show_sc(2, portsc2); +} + +#define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x)) + +struct uhci_td * uhci_link_to_td(unsigned int link) +{ + if (link & 1) + return NULL; + + return bus_to_virt(link & ~15); +} + +void show_queue(struct uhci_qh *qh) +{ + struct uhci_td *td; + int i = 0; + +#if 0 + printk(" link = %p, element = %p\n", qh->link, qh->element); +#endif + if(!qh->element) { + printk(" td 0 = NULL\n"); + return; + } + + for(td = uhci_link_to_td(qh->element); td; + td = uhci_link_to_td(td->link)) { + printk(" td %d = %p\n", i++, td); + printk(" "); + show_td(td); + } +} + +int is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh) +{ + int j; + + for (j = 0; j < UHCI_MAXQH; j++) + if (qh == uhci->root_hub->qh + j) + return 1; + + return 0; +} + +static const char *qh_names[] = {"isochronous", "interrupt2", "interrupt4", + "interrupt8", "interrupt16", "interrupt32", + "interrupt64", "interrupt128", "interrupt256", + "control", "bulk0", "bulk1", "bulk2", "bulk3", + "unused", "unused"}; + +void show_queues(struct uhci *uhci) +{ + int i; + struct uhci_qh *qh; + + for (i = 0; i < UHCI_MAXQH; ++i) { + printk(" %s:\n", qh_names[i]); +#if 0 + printk(" qh #%d, %p\n", i, virt_to_bus(uhci->root_hub->qh + i)); + show_queue(uhci->root_hub->qh + i); +#endif + + qh = uhci_link_to_qh(uhci->root_hub->qh[i].link); + for (; qh; qh = uhci_link_to_qh(qh->link)) { + if (is_skeleton_qh(uhci, qh)) + break; + + show_queue(qh); + } + } +} + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.2.6/linux/drivers/usb/uhci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/uhci.c Wed Apr 28 11:14:03 1999 @@ -0,0 +1,1202 @@ +/* + * Universal Host Controller Interface driver for USB. + * + * (C) Copyright 1999 Linus Torvalds + * + * Intel documents this fairly well, and as far as I know there + * are no royalties or anything like that, but even so there are + * people who decided that they want to do the same thing in a + * completely different way. + * + * Oh, well. The intel version is the more common by far. As such, + * that's the one I care about right now. + * + * WARNING! The USB documentation is downright evil. Most of it + * is just crap, written by a committee. You're better off ignoring + * most of it, the important stuff is: + * - the low-level protocol (fairly simple but lots of small details) + * - working around the horridness of the rest + */ + +/* 4/4/1999 added data toggle for interrupt pipes -keryan */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "uhci.h" +#include "inits.h" + +#ifdef CONFIG_APM +#include +static int handle_apm_event(apm_event_t event); +static int apm_resume = 0; +#endif + +#define compile_assert(x) do { switch (0) { case 1: case !(x): } } while (0) + +int usb_mouse_init(void); +int hub_init(void); + +static struct wait_queue *uhci_configure = NULL; + +/* + * Return the result of a TD.. + */ +static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td) +{ + unsigned int status; + + status = (td->status >> 16) & 0xff; + + /* Some debugging code */ + if (status) { + int i = 10; + struct uhci_td *tmp = dev->control_td; + printk("uhci_td_result() failed with status %d\n", status); + show_status(dev->uhci); + do { + show_td(tmp); + tmp++; + if (!--i) + break; + } while (tmp <= td); + } + return status; +} + +/* + * Inserts a td into qh list at the top. + * + * Careful about atomicity: even on UP this + * requires a locked access due to the concurrent + * DMA engine. + * + * NOTE! This assumes that first->last is a valid + * list of TD's with the proper backpointers set + * up and all.. + */ +static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, struct uhci_td *last) +{ + unsigned int link = qh->element; + unsigned int new = 4 | virt_to_bus(first); + + for (;;) { + unsigned char success; + + last->link = link; + first->backptr = &qh->element; + asm volatile("lock ; cmpxchg %4,%2 ; sete %0" + :"=q" (success), "=a" (link) + :"m" (qh->element), "1" (link), "r" (new) + :"memory"); + if (success) { + /* Was there a successor entry? Fix it's backpointer.. */ + if ((link & 1) == 0) { + struct uhci_td *next = bus_to_virt(link & ~15); + next->backptr = &last->link; + } + break; + } + } +} + +static inline void uhci_insert_td_in_qh(struct uhci_qh *qh, struct uhci_td *td) +{ + uhci_insert_tds_in_qh(qh, td, td); +} + +static void uhci_insert_qh(struct uhci_qh *qh, struct uhci_qh *newqh) +{ + newqh->link = qh->link; + qh->link = virt_to_bus(newqh) | 2; +} + +static void uhci_remove_qh(struct uhci_qh *qh, struct uhci_qh *remqh) +{ + unsigned int remphys = virt_to_bus(remqh); + struct uhci_qh *lqh = qh; + + while ((lqh->link & ~0xF) != remphys) { + if (lqh->link & 1) + break; + + lqh = bus_to_virt(lqh->link & ~0xF); + } + + if (lqh->link & 1) { + printk("couldn't find qh in chain!\n"); + return; + } + + lqh->link = remqh->link; +} + +/* + * Removes td from qh if present. + * + * NOTE! We keep track of both forward and back-pointers, + * so this should be trivial, right? + * + * Wrong. While all TD insert/remove operations are synchronous + * on the CPU, the UHCI controller can (and does) play with the + * very first forward pointer. So we need to validate the backptr + * before we change it, so that we don't by mistake reset the QH + * head to something old. + */ +static void uhci_remove_td(struct uhci_td *td) +{ + unsigned int *backptr = td->backptr; + unsigned int link = td->link; + unsigned int me; + + if (!backptr) + return; + + td->backptr = NULL; + + /* + * This is the easy case: the UHCI will never change "td->link", + * so we can always just look at that and fix up the backpointer + * of any next element.. + */ + if (!(link & 1)) { + struct uhci_td *next = bus_to_virt(link & ~15); + next->backptr = backptr; + } + + /* + * The nasty case is "backptr->next", which we need to + * update to "link" _only_ if "backptr" still points + * to us (it may not: maybe backptr is a QH->element + * pointer and the UHCI has changed the value). + */ + me = virt_to_bus(td) | (0xe & *backptr); + asm volatile("lock ; cmpxchg %0,%1" + : + :"r" (link), "m" (*backptr), "a" (me) + :"memory"); +} + +static struct uhci_qh *uhci_qh_allocate(struct uhci_device *dev) +{ + struct uhci_qh *qh; + int inuse; + + qh = dev->qh; + for (; (inuse = test_and_set_bit(0, &qh->inuse)) != 0 && qh < &dev->qh[UHCI_MAXQH]; qh++) + ; + + if (!inuse) + return(qh); + + printk("ran out of qh's for dev %p\n", dev); + return(NULL); +} + +static void uhci_qh_deallocate(struct uhci_qh *qh) +{ + if (qh->element != 1) + printk("qh %p leaving dangling entries? (%X)\n", qh, qh->element); + + qh->element = 1; + qh->link = 1; + + clear_bit(0, &qh->inuse); +} + +static struct uhci_td *uhci_td_allocate(struct uhci_device *dev) +{ + struct uhci_td *td; + int inuse; + + td = dev->td; + for (; (inuse = test_and_set_bit(0, &td->inuse)) != 0 && td < &dev->td[UHCI_MAXTD]; td++) + ; + + if (!inuse) + return(td); + + printk("ran out of td's for dev %p\n", dev); + return(NULL); +} + +/* + * This MUST only be called when it has been removed from a QH already (or + * the QH has been removed from the skeleton + */ +static void uhci_td_deallocate(struct uhci_td *td) +{ + td->link = 1; + + clear_bit(0, &td->inuse); +} + +/* + * UHCI interrupt list operations.. + */ +static spinlock_t irqlist_lock = SPIN_LOCK_UNLOCKED; + +static void uhci_add_irq_list(struct uhci *uhci, struct uhci_td *td, usb_device_irq completed, void *dev_id) +{ + unsigned long flags; + + td->completed = completed; + td->dev_id = dev_id; + + spin_lock_irqsave(&irqlist_lock, flags); + list_add(&td->irq_list, &uhci->interrupt_list); + spin_unlock_irqrestore(&irqlist_lock, flags); +} + +static void uhci_remove_irq_list(struct uhci_td *td) +{ + unsigned long flags; + + spin_lock_irqsave(&irqlist_lock, flags); + list_del(&td->irq_list); + spin_unlock_irqrestore(&irqlist_lock, flags); +} + +/* + * Request a interrupt handler.. + */ +static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) +{ + struct uhci_device *dev = usb_to_uhci(usb_dev); + struct uhci_td *td = uhci_td_allocate(dev); + struct uhci_qh *interrupt_qh = uhci_qh_allocate(dev); + + unsigned int destination, status; + + /* Destination: pipe destination with INPUT */ + destination = (pipe & 0x0007ff00) | 0x69; + + /* Status: slow/fast, Interrupt, Active, Short Packet Detect Infinite Errors */ + status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23) | (1 << 29) | (0 << 27); + + if(interrupt_qh->element != 1) + printk("interrupt_qh->element = 0x%x\n", + interrupt_qh->element); + + td->link = 1; + td->status = status; /* In */ + td->info = destination | (7 << 21); /* 8 bytes of data */ + td->buffer = virt_to_bus(dev->data); + td->qh = interrupt_qh; + interrupt_qh->skel = &dev->uhci->root_hub->skel_int8_qh; + + uhci_add_irq_list(dev->uhci, td, handler, dev_id); + + uhci_insert_td_in_qh(interrupt_qh, td); + + /* Add it into the skeleton */ + uhci_insert_qh(&dev->uhci->root_hub->skel_int8_qh, interrupt_qh); + return 0; +} + +/* + * Control thread operations: we just mark the last TD + * in a control thread as an interrupt TD, and wake up + * the front-end on completion. + * + * We need to remove the TD from the lists (both interrupt + * list and TD lists) by hand if something bad happens! + */ +static struct wait_queue *control_wakeup; + +static int uhci_control_completed(int status, void *buffer, void *dev_id) +{ + wake_up(&control_wakeup); + return 0; /* Don't re-instate */ +} + +/* td points to the last td in the list, which interrupts on completion */ +static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last) +{ + struct wait_queue wait = { current, NULL }; + struct uhci_qh *ctrl_qh = uhci_qh_allocate(dev); + struct uhci_td *curtd; + + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&control_wakeup, &wait); + + uhci_add_irq_list(dev->uhci, last, uhci_control_completed, NULL); + + /* FIXME: This is kinda kludged */ + /* Walk the TD list and update the QH pointer */ + { + int maxcount = 100; + + curtd = first; + do { + curtd->qh = ctrl_qh; + if (curtd->link & 1) + break; + + curtd = bus_to_virt(curtd->link & ~0xF); + if (!--maxcount) { + printk("runaway tds!\n"); + break; + } + } while (1); + } + + uhci_insert_tds_in_qh(ctrl_qh, first, last); + + /* Add it into the skeleton */ + uhci_insert_qh(&dev->uhci->root_hub->skel_control_qh, ctrl_qh); + + schedule_timeout(HZ/10); + + remove_wait_queue(&control_wakeup, &wait); + + /* Clean up in case it failed.. */ + uhci_remove_irq_list(last); + +#if 0 + printk("Looking for tds [%p, %p]\n", dev->control_td, td); +#endif + + /* Remove it from the skeleton */ + uhci_remove_qh(&dev->uhci->root_hub->skel_control_qh, ctrl_qh); + + uhci_qh_deallocate(ctrl_qh); + + return uhci_td_result(dev, last); +} + +/* + * Send or receive a control message on a pipe. + * + * Note that the "pipe" structure is set up to map + * easily to the uhci destination fields. + * + * A control message is built up from three parts: + * - The command itself + * - [ optional ] data phase + * - Status complete phase + * + * The data phase can be an arbitrary number of TD's + * although we currently had better not have more than + * 29 TD's here (we have 31 TD's allocated for control + * operations, and two of them are used for command and + * status). + * + * 29 TD's is a minimum of 232 bytes worth of control + * information, that's just ridiculously high. Most + * control messages have just a few bytes of data. + */ +static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len) +{ + struct uhci_device *dev = usb_to_uhci(usb_dev); + struct uhci_td *first, *td, *prevtd; + unsigned long destination, status; + int ret; + + if (len > usb_maxpacket(usb_dev->maxpacketsize) * 29) + printk("Warning, too much data for a control packet, crashing\n"); + + first = td = uhci_td_allocate(dev); + + /* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */ + destination = (pipe & 0x0007ff00) | 0x2D; + + /* Status: slow/fast, Active, Short Packet Detect Three Errors */ + status = (pipe & (1 << 26)) | (1 << 23) | (1 << 29) | (3 << 27); + + /* + * Build the TD for the control request + */ + td->status = status; /* Try forever */ + td->info = destination | (7 << 21); /* 8 bytes of data */ + td->buffer = virt_to_bus(cmd); + + /* + * If direction is "send", change the frame from SETUP (0x2D) + * to OUT (0xE1). Else change it from SETUP to IN (0x69) + */ + destination ^= (0x2D ^ 0x69); /* SETUP -> IN */ + if (usb_pipeout(pipe)) + destination ^= (0xE1 ^ 0x69); /* IN -> OUT */ + + prevtd = td; + td = uhci_td_allocate(dev); + prevtd->link = 4 | virt_to_bus(td); + + /* + * Build the DATA TD's + */ + while (len > 0) { + /* Build the TD for control status */ + int pktsze = len; + int maxsze = usb_maxpacket(pipe); + + if (pktsze > maxsze) + pktsze = maxsze; + + /* Alternate Data0/1 (start with Data1) */ + destination ^= 1 << 19; + + td->status = status; /* Status */ + td->info = destination | ((pktsze-1) << 21); /* pktsze bytes of data */ + td->buffer = virt_to_bus(data); + td->backptr = &prevtd->link; + + prevtd = td; + td = uhci_td_allocate(dev); + prevtd->link = 4 | virt_to_bus(td); /* Update previous TD */ + + data += maxsze; + len -= maxsze; + } + + /* + * Build the final TD for control status + */ + destination ^= (0xE1 ^ 0x69); /* OUT -> IN */ + destination |= 1 << 19; /* End in Data1 */ + + td->link = 1; /* Terminate */ + td->status = status | (1 << 24); /* IOC */ + td->info = destination | (0x7ff << 21); /* 0 bytes of data */ + td->buffer = 0; + td->backptr = &prevtd->link; + + /* Start it up.. */ + ret = uhci_run_control(dev, first, td); + + { + int maxcount = 100; + struct uhci_td *curtd = first; + unsigned int nextlink; + + do { + nextlink = curtd->link; + uhci_remove_td(curtd); + uhci_td_deallocate(curtd); + if (nextlink & 1) /* Tail? */ + break; + + curtd = bus_to_virt(nextlink & ~0xF); + if (!--maxcount) { + printk("runaway td's!?\n"); + break; + } + } while (1); + } + + return ret; +} + +static struct usb_device *uhci_usb_allocate(struct usb_device *parent) +{ + struct usb_device *usb_dev; + struct uhci_device *dev; + int i; + + usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL); + if (!usb_dev) + return NULL; + + memset(usb_dev, 0, sizeof(*usb_dev)); + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + kfree(usb_dev); + return NULL; + } + + /* Initialize "dev" */ + memset(dev, 0, sizeof(*dev)); + + usb_dev->hcpriv = dev; + dev->usb = usb_dev; + + usb_dev->parent = parent; + + if (parent) { + usb_dev->bus = parent->bus; + dev->uhci = usb_to_uhci(parent)->uhci; + } + + /* Reset the QH's and TD's */ + for (i = 0; i < UHCI_MAXQH; i++) { + dev->qh[i].link = 1; + dev->qh[i].element = 1; + dev->qh[i].inuse = 0; + } + + for (i = 0; i < UHCI_MAXTD; i++) { + dev->td[i].link = 1; + dev->td[i].inuse = 0; + } + + return usb_dev; +} + +static int uhci_usb_deallocate(struct usb_device *usb_dev) +{ + struct uhci_device *dev = usb_to_uhci(usb_dev); + int i; + + /* There are UHCI_MAXTD preallocated tds */ + for (i = 0; i < UHCI_MAXTD; ++i) { + struct uhci_td *td = dev->td + i; + + /* And remove it from the irq list, if it's active */ + if (td->status & (1 << 23)) + uhci_remove_irq_list(td); + + if (td->inuse) + uhci_remove_td(td); + } + + /* Remove the td from any queues */ + for (i = 0; i < UHCI_MAXQH; ++i) { + struct uhci_qh *qh = dev->qh + i; + + if (qh->inuse) + uhci_remove_qh(qh->skel, qh); + } + + kfree(dev); + kfree(usb_dev); + + return 0; +} + +struct usb_operations uhci_device_operations = { + uhci_usb_allocate, + uhci_usb_deallocate, + uhci_control_msg, + uhci_request_irq, +}; + +/* + * This is just incredibly fragile. The timings must be just + * right, and they aren't really documented very well. + * + * Note the short delay between disabling reset and enabling + * the port.. + */ +static void uhci_reset_port(unsigned int port) +{ + unsigned short status; + + status = inw(port); + outw(status | USBPORTSC_PR, port); /* reset port */ + wait_ms(10); + outw(status & ~USBPORTSC_PR, port); + udelay(5); + + status = inw(port); + outw(status | USBPORTSC_PE, port); /* enable port */ + wait_ms(10); + + status = inw(port); + if(!(status & USBPORTSC_PE)) { + outw(status | USBPORTSC_PE, port); /* one more try at enabling port */ + wait_ms(50); + } + +} + + +/* + * This gets called if the connect status on the root + * hub (and the root hub only) changes. + */ +static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned int nr) +{ + struct usb_device *usb_dev; + struct uhci_device *dev; + unsigned short status; + + printk("uhci_connect_change: called for %d\n", nr); + + /* + * Even if the status says we're connected, + * the fact that the status bits changed may + * that we got disconnected and then reconnected. + * + * So start off by getting rid of any old devices.. + */ + usb_disconnect(&uhci->root_hub->usb->children[nr]); + + status = inw(port); + + /* If we have nothing connected, then clear change status and disable the port */ + status = (status & ~USBPORTSC_PE) | USBPORTSC_PEC; + if (!(status & USBPORTSC_CCS)) { + outw(status, port); + return; + } + + /* + * Ok, we got a new connection. Allocate a device to it, + * and find out what it wants to do.. + */ + usb_dev = uhci_usb_allocate(uhci->root_hub->usb); + dev = usb_dev->hcpriv; + + dev->uhci = uhci; + + usb_connect(usb_dev); + + uhci->root_hub->usb->children[nr] = usb_dev; + + wait_ms(200); /* wait for powerup */ + uhci_reset_port(port); + + /* Get speed information */ + usb_dev->slow = (inw(port) & USBPORTSC_LSDA) ? 1 : 0; + + /* + * Ok, all the stuff specific to the root hub has been done. + * The rest is generic for any new USB attach, regardless of + * hub type. + */ + usb_new_device(usb_dev); +} + +/* + * This gets called when the root hub configuration + * has changed. Just go through each port, seeing if + * there is something interesting happening. + */ +static void uhci_check_configuration(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr + USBPORTSC1; + int maxchild = uhci->root_hub->usb->maxchild; + int nr = 0; + + do { + unsigned short status = inw(io_addr); + + if (status & USBPORTSC_CSC) + uhci_connect_change(uhci, io_addr, nr); + + nr++; io_addr += 2; + } while (nr < maxchild); +} + +static void uhci_interrupt_notify(struct uhci *uhci) +{ + struct list_head *head = &uhci->interrupt_list; + struct list_head *tmp; + + spin_lock(&irqlist_lock); + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list); + struct list_head *next; + + next = tmp->next; + + if (!(td->status & (1 << 23))) { /* No longer active? */ + /* remove from IRQ list */ + __list_del(tmp->prev, next); + INIT_LIST_HEAD(tmp); + if (td->completed(td->status, bus_to_virt(td->buffer), td->dev_id)) { + struct uhci_qh *interrupt_qh = td->qh; + + list_add(&td->irq_list, &uhci->interrupt_list); + td->info ^= 1 << 19; /* toggle between data0 and data1 */ + td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */ + + /* Remove then readd? Is that necessary */ + uhci_remove_td(td); + uhci_insert_td_in_qh(interrupt_qh, td); + } + /* If completed wants to not reactivate, then it's */ + /* responsible for free'ing the TD's and QH's */ + /* or another function (such as run_control) */ + } + tmp = next; + } + spin_unlock(&irqlist_lock); +} + +/* + * Check port status - Connect Status Change - for + * each of the attached ports (defaults to two ports, + * but at least in theory there can be more of them). + * + * Wake up the configurator if something happened, we + * can't really do much at interrupt time. + */ +static void uhci_root_hub_events(struct uhci *uhci, unsigned int io_addr) +{ + if (waitqueue_active(&uhci_configure)) { + int ports = uhci->root_hub->usb->maxchild; + io_addr += USBPORTSC1; + do { + if (inw(io_addr) & USBPORTSC_CSC) { + wake_up(&uhci_configure); + return; + } + io_addr += 2; + } while (--ports > 0); + } +} + +static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs) +{ + struct uhci *uhci = __uhci; + unsigned int io_addr = uhci->io_addr; + unsigned short status; + + /* + * Read the interrupt status, and write it back to clear the interrupt cause + */ + status = inw(io_addr + USBSTS); + outw(status, io_addr + USBSTS); + + /* Walk the list of pending TD's to see which ones completed.. */ + uhci_interrupt_notify(uhci); + + /* Check if there are any events on the root hub.. */ + uhci_root_hub_events(uhci, io_addr); +} + +/* + * We init one packet, and mark it just IOC and _not_ + * active. Which will result in no actual USB traffic, + * but _will_ result in an interrupt every second. + * + * Which is exactly what we want. + */ +static void uhci_init_ticktd(struct uhci *uhci) +{ + struct uhci_device *dev = uhci->root_hub; + struct uhci_td *td = uhci_td_allocate(dev); + + td->link = 1; + td->status = (1 << 24); /* interrupt on completion */ + td->info = (15 << 21) | 0x7f69; /* (ignored) input packet, 16 bytes, device 127 */ + td->buffer = 0; + td->qh = NULL; + + uhci->fl->frame[0] = virt_to_bus(td); +} + +static void reset_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + + /* Global reset for 50ms */ + outw(USBCMD_GRESET, io_addr+USBCMD); + wait_ms(50); + outw(0, io_addr+USBCMD); + wait_ms(10); +} + +static void start_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + int timeout = 1000; + + uhci_init_ticktd(uhci); + + /* + * Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + outw(USBCMD_HCRESET, io_addr + USBCMD); + while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + printk("USBCMD_HCRESET timed out!\n"); + break; + } + } + + outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); + outw(0, io_addr + USBFRNUM); + outl(virt_to_bus(uhci->fl), io_addr + USBFLBASEADD); + + /* Run and mark it configured with a 64-byte max packet */ + outw(USBCMD_RS | USBCMD_CF, io_addr + USBCMD); +} + +/* + * Allocate a frame list, and four regular queues. + * + * The hardware doesn't really know any difference + * in the queues, but the order does matter for the + * protocols higher up. The order is: + * + * - any isochronous events handled before any + * of the queues. We don't do that here, because + * we'll create the actual TD entries on demand. + * - The first queue is the "interrupt queue". + * - The second queue is the "control queue". + * - The third queue is "bulk data". + * + * We could certainly have multiple queues of the same + * type, and maybe we should. We could have per-device + * queues, for example. We begin small. + */ +static struct uhci *alloc_uhci(unsigned int io_addr) +{ + int i; + struct uhci *uhci; + struct usb_bus *bus; + struct uhci_device *dev; + struct usb_device *usb; + + uhci = kmalloc(sizeof(*uhci), GFP_KERNEL); + if (!uhci) + return NULL; + + memset(uhci, 0, sizeof(*uhci)); + + uhci->irq = -1; + uhci->io_addr = io_addr; + INIT_LIST_HEAD(&uhci->interrupt_list); + + /* We need exactly one page (per UHCI specs), how convenient */ + uhci->fl = (void *)__get_free_page(GFP_KERNEL); + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return NULL; + + memset(bus, 0, sizeof(*bus)); + + uhci->bus = bus; + bus->hcpriv = uhci; + bus->op = &uhci_device_operations; + + /* + * We allocate a 8kB area for the UHCI hub. The area + * is described by the uhci_device structure, and basically + * contains everything needed for normal operation. + * + * The first page is the actual device descriptor for the + * hub. + * + * The second page is used for the frame list. + */ + usb = uhci_usb_allocate(NULL); + if (!usb) + return NULL; + + dev = uhci->root_hub = usb_to_uhci(usb); + + usb->bus = bus; + + /* Initialize the root hub */ + /* UHCI specs says devices must have 2 ports, but goes on to say */ + /* they may have more but give no way to determine how many they */ + /* have, so default to 2 */ + usb->maxchild = 2; + usb_init_root_hub(usb); + + /* + * Initialize the queues. They all start out empty, + * linked to each other in the proper order. + */ + for (i = 1 ; i < 9; i++) { + dev->qh[i].link = 2 | virt_to_bus(&dev->skel_control_qh); + dev->qh[i].element = 1; + } + + dev->skel_control_qh.link = 2 | virt_to_bus(&dev->skel_bulk0_qh); + dev->skel_control_qh.element = 1; + + dev->skel_bulk0_qh.link = 2 | virt_to_bus(&dev->skel_bulk1_qh); + dev->skel_bulk0_qh.element = 1; + + dev->skel_bulk1_qh.link = 2 | virt_to_bus(&dev->skel_bulk2_qh); + dev->skel_bulk1_qh.element = 1; + + dev->skel_bulk2_qh.link = 2 | virt_to_bus(&dev->skel_bulk3_qh); + dev->skel_bulk2_qh.element = 1; + + dev->skel_bulk3_qh.link = 1; + dev->skel_bulk3_qh.element = 1; + + /* + * Fill the frame list: make all entries point to + * the proper interrupt queue. + * + * This is probably silly, but it's a simple way to + * scatter the interrupt queues in a way that gives + * us a reasonable dynamic range for irq latencies. + */ + for (i = 0; i < 1024; i++) { + struct uhci_qh * irq = &dev->skel_int2_qh; + if (i & 1) { + irq++; + if (i & 2) { + irq++; + if (i & 4) { + irq++; + if (i & 8) { + irq++; + if (i & 16) { + irq++; + if (i & 32) { + irq++; + if (i & 64) { + irq++; + } + } + } + } + } + } + } + uhci->fl->frame[i] = 2 | virt_to_bus(irq); + } + + return uhci; +} + + +/* + * De-allocate all resources.. + */ +static void release_uhci(struct uhci *uhci) +{ + if (uhci->irq >= 0) { + free_irq(uhci->irq, uhci); + uhci->irq = -1; + } + +#if 0 + if (uhci->root_hub) { + uhci_usb_deallocate(uhci_to_usb(uhci->root_hub)); + uhci->root_hub = NULL; + } +#endif + + if (uhci->fl) { + free_page((unsigned long)uhci->fl); + uhci->fl = NULL; + } + + kfree(uhci->bus); + kfree(uhci); +} + +static int uhci_control_thread(void * __uhci) +{ + struct uhci *uhci = (struct uhci *)__uhci; + + lock_kernel(); + request_region(uhci->io_addr, 32, "usb-uhci"); + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources.. + */ + printk("uhci_control_thread at %p\n", &uhci_control_thread); + exit_mm(current); + exit_files(current); + exit_fs(current); + + strcpy(current->comm, "uhci-control"); + + /* + * Ok, all systems are go.. + */ + start_hc(uhci); + for(;;) { + siginfo_t info; + int unsigned long signr; + + interruptible_sleep_on(&uhci_configure); +#ifdef CONFIG_APM + if (apm_resume) { + apm_resume = 0; + start_hc(uhci); + continue; + } +#endif + uhci_check_configuration(uhci); + + if(signal_pending(current)) { + /* sending SIGUSR1 makes us print out some info */ + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if(signr == SIGUSR1) { + printk("UHCI queue dump:\n"); + show_queues(uhci); + } else { + break; + } + } + } + +#if 0 + if(uhci->root_hub) + for(i = 0; i < uhci->root_hub->usb->maxchild; i++) + usb_disconnect(uhci->root_hub->usb->children + i); +#endif + + reset_hc(uhci); + release_region(uhci->io_addr, 32); + + release_uhci(uhci); + MOD_DEC_USE_COUNT; + + printk("uhci_control_thread exiting\n"); + + return 0; +} + +/* + * If we've successfully found a UHCI, now is the time to increment the + * module usage count, start the control thread, and return success.. + */ +static int found_uhci(int irq, unsigned int io_addr) +{ + int retval; + struct uhci *uhci; + + uhci = alloc_uhci(io_addr); + if (!uhci) + return -ENOMEM; + + reset_hc(uhci); + + retval = -EBUSY; + if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb", uhci) == 0) { + int pid; + + MOD_INC_USE_COUNT; + uhci->irq = irq; + pid = kernel_thread(uhci_control_thread, uhci, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (pid >= 0) + return 0; + + MOD_DEC_USE_COUNT; + retval = pid; + } + release_uhci(uhci); + return retval; +} + +static int start_uhci(struct pci_dev *dev) +{ + int i; + + /* Search for the IO base address.. */ + for (i = 0; i < 6; i++) { + unsigned int io_addr = dev->base_address[i]; + + /* IO address? */ + if (!(io_addr & 1)) + continue; + + io_addr &= PCI_BASE_ADDRESS_IO_MASK; + + /* Is it already in use? */ + if (check_region(io_addr, 32)) + break; + + return found_uhci(dev->irq, io_addr); + } + return -1; +} + +#ifdef CONFIG_APM +static int handle_apm_event(apm_event_t event) +{ + static int down = 0; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + if (down) { + printk(KERN_DEBUG "uhci: received extra suspend event\n"); + break; + } + down = 1; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + if (!down) { + printk(KERN_DEBUG "uhci: received bogus resume event\n"); + break; + } + down = 0; + if (waitqueue_active(&uhci_configure)) { + apm_resume = 1; + wake_up(&uhci_configure); + } + break; + } + return 0; +} +#endif + +#ifdef MODULE + +void cleanup_module(void) +{ +#ifdef CONFIG_APM + apm_unregister_callback(&handle_apm_event); +#endif +} + +#define uhci_init init_module + +#endif + +int uhci_init(void) +{ + int retval; + struct pci_dev *dev = NULL; + u8 type; + + retval = -ENODEV; + for (;;) { + dev = pci_find_class(PCI_CLASS_SERIAL_USB<<8, dev); + if (!dev) + break; + /* Is it UHCI */ + pci_read_config_byte(dev, PCI_CLASS_PROG, &type); + if(type != 0) + continue; + /* Ok set it up */ + retval = start_uhci(dev); + if (retval < 0) + continue; + +#ifdef CONFIG_USB_MOUSE + usb_mouse_init(); +#endif +#ifdef CONFIG_USB_KBD + usb_kbd_init(); +#endif + hub_init(); +#ifdef CONFIG_USB_AUDIO + usb_audio_init(); +#endif +#ifdef CONFIG_APM + apm_register_callback(&handle_apm_event); +#endif + + return 0; + } + return retval; +} diff -u --recursive --new-file v2.2.6/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h --- v2.2.6/linux/drivers/usb/uhci.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/uhci.h Wed Apr 28 11:14:03 1999 @@ -0,0 +1,229 @@ +#ifndef __LINUX_UHCI_H +#define __LINUX_UHCI_H + +#include + +#include "usb.h" + +/* + * Universal Host Controller Interface data structures and defines + */ + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +struct uhci_qh { + unsigned int link; /* Next queue */ + unsigned int element; /* Queue element pointer */ + int inuse; /* Inuse? */ + struct uhci_qh *skel; /* Skeleton head */ +} __attribute__((aligned(16))); + +struct uhci_framelist { + unsigned int frame[1024]; +} __attribute__((aligned(4096))); + +/* + * The documentation says "4 words for hardware, 4 words for software". + * + * That's silly, the hardware doesn't care. The hardware only cares that + * the hardware words are 16-byte aligned, and we can have any amount of + * sw space after the TD entry as far as I can tell. + * + * But let's just go with the documentation, at least for 32-bit machines. + * On 64-bit machines we probably want to take advantage of the fact that + * hw doesn't really care about the size of the sw-only area. + * + * Alas, not anymore, we have more than 4 words of software, woops + */ +struct uhci_td { + /* Hardware fields */ + __u32 link; + __u32 status; + __u32 info; + __u32 buffer; + + /* Software fields */ + struct list_head irq_list; /* Active interrupt list.. */ + usb_device_irq completed; /* Completion handler routine */ + unsigned int *backptr; /* Where to remove this from.. */ + void *dev_id; + int inuse; /* Inuse? */ + struct uhci_qh *qh; +} __attribute__((aligned(32))); + +/* + * Note the alignment requirements of the entries + * + * Each UHCI device has pre-allocated QH and TD entries. + * You can use more than the pre-allocated ones, but I + * don't see you usually needing to. + */ +struct uhci; + +#define UHCI_MAXTD 64 + +#define UHCI_MAXQH 16 + +/* The usb device part must be first! */ +struct uhci_device { + struct usb_device *usb; + + struct uhci *uhci; + struct uhci_qh qh[UHCI_MAXQH]; /* These are the "common" qh's for each device */ + struct uhci_td td[UHCI_MAXTD]; + + unsigned long data[16]; +}; + +#define uhci_to_usb(uhci) ((uhci)->usb) +#define usb_to_uhci(usb) ((struct uhci_device *)(usb)->hcpriv) + +/* + * The root hub pre-allocated QH's and TD's have + * some special global uses.. + */ +#define control_td td /* Td's 0-30 */ +/* This is only for the root hub's TD list */ +#define tick_td td[31] + +/* + * There are various standard queues. We set up several different + * queues for each of the three basic queue types: interrupt, + * control, and bulk. + * + * - There are various different interrupt latencies: ranging from + * every other USB frame (2 ms apart) to every 256 USB frames (ie + * 256 ms apart). Make your choice according to how obnoxious you + * want to be on the wire, vs how critical latency is for you. + * - The control list is done every frame. + * - There are 4 bulk lists, so that up to four devices can have a + * bulk list of their own and when run concurrently all four lists + * will be be serviced. + * + * This is a bit misleading, there are various interrupt latencies, but they + * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the + * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor + * problem + * + * In the case of the root hub, these QH's are just head's of qh's. Don't + * be scared, it kinda makes sense. Look at this wonderful picture care of + * Linus: + * + * generic-iso-QH -> dev1-iso-QH -> generic-irq-QH -> dev1-irq-QH -> ... + * | | | | + * End dev1-iso-TD1 End dev1-irq-TD1 + * | + * dev1-iso-TD2 + * | + * .... + * + * This may vary a bit (the UHCI docs don't explicitly say you can put iso + * transfers in QH's and all of their pictures don't have that either) but + * other than that, that is what we're doing now + * + * To keep with Linus' nomenclature, this is called the qh skeleton. These + * labels (below) are only signficant to the root hub's qh's + */ +#define skel_iso_qh qh[0] + +#define skel_int2_qh qh[1] +#define skel_int4_qh qh[2] +#define skel_int8_qh qh[3] +#define skel_int16_qh qh[4] +#define skel_int32_qh qh[5] +#define skel_int64_qh qh[6] +#define skel_int128_qh qh[7] +#define skel_int256_qh qh[8] + +#define skel_control_qh qh[9] + +#define skel_bulk0_qh qh[10] +#define skel_bulk1_qh qh[11] +#define skel_bulk2_qh qh[12] +#define skel_bulk3_qh qh[13] + +/* + * These are significant to the devices allocation of QH's + */ +#if 0 +#define iso_qh qh[0] +#define int_qh qh[1] /* We have 2 "common" interrupt QH's */ +#define control_qh qh[3] +#define bulk_qh qh[4] /* We have 4 "common" bulk QH's */ +#define extra_qh qh[8] /* The rest, anything goes */ +#endif + +/* + * This describes the full uhci information. + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. + */ +struct uhci { + int irq; + unsigned int io_addr; + + struct usb_bus *bus; + +#if 0 + /* These are "standard" QH's for the entire bus */ + struct uhci_qh qh[UHCI_MAXQH]; +#endif + struct uhci_device *root_hub; /* Root hub device descriptor.. */ + + struct uhci_framelist *fl; /* Frame list */ + struct list_head interrupt_list; /* List of interrupt-active TD's for this uhci */ +}; + +/* needed for the debugging code */ +struct uhci_td *uhci_link_to_td(unsigned int element); + +/* Debugging code */ +void show_td(struct uhci_td * td); +void show_status(struct uhci *uhci); +void show_queues(struct uhci *uhci); + +#endif + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c --- v2.2.6/linux/drivers/usb/usb-debug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usb-debug.c Wed Apr 21 02:32:59 1999 @@ -0,0 +1,127 @@ +/* + * debug.c - USB debug helper routines. + * + * I just want these out of the way where they aren't in your + * face, but so that you can still use them.. + */ +#include + +#include "usb.h" + +static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint) +{ + usb_show_endpoint_descriptor(endpoint); +} + +static void usb_show_interface(struct usb_interface_descriptor *interface) +{ + int i; + + usb_show_interface_descriptor(interface); + for (i = 0 ; i < interface->bNumEndpoints; i++) + usb_show_endpoint(interface->endpoint + i); +} + +static void usb_show_config(struct usb_config_descriptor *config) +{ + int i; + + usb_show_config_descriptor(config); + for (i = 0 ; i < config->bNumInterfaces; i++) + usb_show_interface(config->interface + i); +} + +void usb_show_device(struct usb_device *dev) +{ + int i; + + usb_show_device_descriptor(&dev->descriptor); + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + usb_show_config(dev->config + i); +} + + +/* + * Parse and show the different USB descriptors. + */ +void usb_show_device_descriptor(struct usb_device_descriptor *desc) +{ + printk(" USB version %x.%02x\n", desc->bcdUSB >> 8, desc->bcdUSB & 0xff); + printk(" Vendor: %04x\n", desc->idVendor); + printk(" Product: %04x\n", desc->idProduct); + printk(" Configurations: %d\n", desc->bNumConfigurations); + + printk(" Device Class: %d\n", desc->bDeviceClass); + switch (desc->bDeviceClass) { + case 0: + printk(" Per-interface classes\n"); + break; + case 9: + printk(" Hub device class\n"); + break; + case 0xff: + printk(" Vendor class\n"); + break; + default: + printk(" Unknown class\n"); + } +} + +void usb_show_config_descriptor(struct usb_config_descriptor * desc) +{ + printk("Configuration:\n"); + printk(" bLength = %4d%s\n", desc->bLength, + desc->bLength == 9 ? "" : " (!!!)"); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" wTotalLength = %04x\n", desc->wTotalLength); + printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces); + printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue); + printk(" iConfiguration = %02x\n", desc->iConfiguration); + printk(" bmAttributes = %02x\n", desc->bmAttributes); + printk(" MaxPower = %4dmA\n", desc->MaxPower * 2); +} + +void usb_show_interface_descriptor(struct usb_interface_descriptor * desc) +{ + printk(" Interface:\n"); + printk(" bLength = %4d%s\n", desc->bLength, + desc->bLength == 9 ? "" : " (!!!)"); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber); + printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting); + printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints); + printk(" bInterfaceClass = %02x\n", desc->bInterfaceClass); + printk(" bInterfaceSubClass = %02x\n", desc->bInterfaceSubClass); + printk(" bInterfaceProtocol = %02x\n", desc->bInterfaceProtocol); + printk(" iInterface = %02x\n", desc->iInterface); +} + +void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor * desc) +{ + char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" }; + printk(" Endpoint:\n"); + printk(" bLength = %4d%s\n", desc->bLength, + desc->bLength == 7 ? "" : " (!!!)"); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress, + (desc->bEndpointAddress & 0x80) ? "in" : "out"); + printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes, + EndpointType[3 & desc->bmAttributes]); + printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize); + printk(" bInterval = %02x\n", desc->bInterval); +} + +void usb_show_hub_descriptor(struct usb_hub_descriptor * desc) +{ + int len = 7; + unsigned char *ptr = (unsigned char *) desc; + + printk("Interface:"); + while (len) { + printk(" %02x", *ptr); + ptr++; len--; + } + printk("\n"); +} + + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.2.6/linux/drivers/usb/usb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usb.c Wed Apr 28 11:14:03 1999 @@ -0,0 +1,616 @@ +/* + * driver/usb/usb.c + * + * (C) Copyright Linus Torvalds 1999 + * + * NOTE! This is not actually a driver at all, rather this is + * just a collection of helper routines that implement the + * generic USB things that the real drivers can use.. + * + * Think of this as a "USB library" rather than anything else. + * It should be considered a slave, with no callbacks. Callbacks + * are evil. + */ + +/* + * Table 9-2 + * + * Offset Field Size Value Desc + * 0 bmRequestType 1 Bitmap D7: Direction + * 0 = Host-to-device + * 1 = Device-to-host + * D6..5: Type + * 0 = Standard + * 1 = Class + * 2 = Vendor + * 3 = Reserved + * D4..0: Recipient + * 0 = Device + * 1 = Interface + * 2 = Endpoint + * 3 = Other + * 4..31 = Reserved + * 1 bRequest 1 Value Specific request (9-3) + * 2 wValue 2 Value Varies + * 4 wIndex 2 Index/Offset Varies + * 6 wLength 2 Count Bytes for data + */ + +#include +#include +#include + +#include "usb.h" + +/* + * We have a per-interface "registered driver" list. + */ +static LIST_HEAD(usb_driver_list); + +int usb_register(struct usb_driver *new_driver) +{ + /* Add it to the list of known drivers */ + list_add(&new_driver->driver_list, &usb_driver_list); + + /* + * We should go through all existing devices, and see if any of + * them would be acceptable to the new driver.. Let's do that + * in version 2.0. + */ + return 0; +} + +void usb_deregister(struct usb_driver *driver) +{ + list_del(&driver->driver_list); +} + +/* + * This entrypoint gets called for each new device. + * + * We now walk the list of registered USB drivers, + * looking for one that will accept this device as + * his.. + */ +void usb_device_descriptor(struct usb_device *dev) +{ + struct list_head *tmp = usb_driver_list.next; + + while (tmp != &usb_driver_list) { + struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list); + tmp = tmp->next; + if (driver->probe(dev)) + continue; + dev->driver = driver; + return; + } + + /* + * Ok, no driver accepted the device, so show the info + * for debugging.. + */ + printk("Unknown new USB device:\n"); + usb_show_device(dev); +} + +/* + * Parse the fairly incomprehensible output of + * the USB configuration data, and build up the + * USB device database. + */ +static int usb_expect_descriptor(unsigned char *ptr, int len, unsigned char desctype, unsigned char descindex) +{ + int parsed = 0; + int n_len; + unsigned short n_desc; + + for (;;) { + int i; + + if (len < descindex) + return -1; + n_desc = *(unsigned short *)ptr; + n_len = n_desc & 0xff; + + if (n_desc == ((desctype << 8) + descindex)) + break; + + if (((n_desc >> 8)&0xFF) == desctype && + n_len > descindex) + { + printk("bug: oversized descriptor.\n"); + break; + } + + if (n_len < 2 || n_len > len) + { + printk("Short descriptor.\n"); + return -1; + } + printk( + "Expected descriptor %02X/%02X, got %02X/%02X - skipping\n", + desctype, descindex, + (n_desc >> 8) & 0xFF, n_desc & 0xFF); + for (i = 0 ; i < n_len; i++) + printk(" %d %02x\n", i, ptr[i]); + len -= n_len; + ptr += n_len; + parsed += n_len; + } + + printk("Found %02X:%02X\n", + desctype, descindex); + return parsed; +} + +/* + * Parse the even more incomprehensible mess made of the USB spec + * by USB audio having private magic to go with it. + */ + +static int usb_check_descriptor(unsigned char *ptr, int len, unsigned char desctype) +{ + int n_len = ptr[0]; + + if (n_len < 2 || n_len > len) + { + printk("Short descriptor.\n"); + return -1; + } + + if (ptr[1] == desctype) + return 0; + + return -1; +} + + +static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *ptr, int len) +{ + int parsed = usb_expect_descriptor(ptr, len, USB_DT_ENDPOINT, 7); + int i; + + if (parsed < 0) + return parsed; + memcpy(endpoint, ptr + parsed, ptr[parsed]); + + parsed += ptr[parsed]; + len -= ptr[parsed]; + + while((i = usb_check_descriptor(ptr+parsed, len, 0x25))>=0) + { + usb_audio_endpoint(endpoint, ptr+parsed+i); + len -= ptr[parsed+i]; + parsed += ptr[parsed+i]; + } + + return parsed;// + ptr[parsed]; +} + +static int usb_parse_interface(struct usb_device *dev, struct usb_interface_descriptor *interface, unsigned char *ptr, int len) +{ + int i; + int parsed = usb_expect_descriptor(ptr, len, USB_DT_INTERFACE, 9); + int retval; + + if (parsed < 0) + return parsed; + + memcpy(interface, ptr + parsed, *ptr); + len -= ptr[parsed]; + parsed += ptr[parsed]; + + while((i=usb_check_descriptor(ptr+parsed, len, 0x24))>=0) + { + usb_audio_interface(interface, ptr+parsed+i); + len -= ptr[parsed+i]; + parsed += ptr[parsed+i]; + } + + if (interface->bNumEndpoints > USB_MAXENDPOINTS) + { + printk(KERN_WARNING "usb: too many endpoints.\n"); + return -1; + } + + for (i = 0; i < interface->bNumEndpoints; i++) { +// if(((USB_DT_HID << 8) | 9) == *(unsigned short*)(ptr + parsed)) { +// parsed += 9; /* skip over the HID descriptor for now */ +// len -= 9; +// } + retval = usb_parse_endpoint(dev, interface->endpoint + i, ptr + parsed, len); + if (retval < 0) return retval; + parsed += retval; + len -= retval; + } + return parsed; +} + +static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor *config, unsigned char *ptr, int len) +{ + int i; + int parsed = usb_expect_descriptor(ptr, len, USB_DT_CONFIG, 9); + + if (parsed < 0) + return parsed; + + memcpy(config, ptr + parsed, *ptr); + len -= *ptr; + parsed += *ptr; + + if (config->bNumInterfaces > USB_MAXINTERFACES) + { + printk(KERN_WARNING "usb: too many interfaces.\n"); + return -1; + } + + for (i = 0; i < config->bNumInterfaces; i++) { + int retval = usb_parse_interface(dev, config->interface + i, ptr + parsed, len); + if (retval < 0) + return parsed; // HACK +// return retval; + parsed += retval; + len -= retval; + } + return parsed; +} + +int usb_parse_configuration(struct usb_device *dev, void *__buf, int bytes) +{ + int i; + unsigned char *ptr = __buf; + + if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) + { + printk(KERN_WARNING "usb: too many configurations.\n"); + return -1; + } + + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { + int retval = usb_parse_config(dev, dev->config + i, ptr, bytes); + if (retval < 0) + return retval; + ptr += retval; + bytes += retval; + } + return 0; +} + +void usb_init_root_hub(struct usb_device *dev) +{ + dev->devnum = -1; + dev->slow = 0; +} + +/* + * Something got disconnected. Get rid of it, and all of its children. + */ +void usb_disconnect(struct usb_device **pdev) +{ + struct usb_device * dev = *pdev; + + if (dev) { + int i; + + *pdev = NULL; + + printk("USB disconnect on device %d\n", dev->devnum); + + if(dev->driver) dev->driver->disconnect(dev); + + /* Free up all the children.. */ + for (i = 0; i < USB_MAXCHILDREN; i++) { + struct usb_device **child = dev->children + i; + usb_disconnect(child); + } + + /* Free up the device itself, including its device number */ + if (dev->devnum > 0) + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); + dev->bus->op->deallocate(dev); + } +} + + +/* + * Connect a new USB device. This basically just initializes + * the USB device information and sets up the topology - it's + * up to the low-level driver to reset the port and actually + * do the setup (the upper levels don't know how to do that). + */ +void usb_connect(struct usb_device *dev) +{ + int devnum; + + dev->descriptor.bMaxPacketSize0 = 8; /* XXX fixed 8 bytes for now */ + + devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); + if (devnum < 128) { + set_bit(devnum, dev->bus->devmap.devicemap); + dev->devnum = devnum; + } +} + +/* + * These are the actual routines to send + * and receive control messages. + */ +int usb_set_address(struct usb_device *dev) +{ + devrequest dr; + + dr.requesttype = 0; + dr.request = USB_REQ_SET_ADDRESS; + dr.value = dev->devnum; + dr.index = 0; + dr.length = 0; + + return dev->bus->op->control_msg(dev, usb_snddefctrl(dev), &dr, NULL, 0); +} + +int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) +{ + devrequest dr; + + dr.requesttype = 0x80; + dr.request = USB_REQ_GET_DESCRIPTOR; + dr.value = (type << 8) + index; + dr.index = 0; + dr.length = size; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, size); +} + +int usb_get_device_descriptor(struct usb_device *dev) +{ + return usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); +} + +int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) +{ + devrequest dr; + + dr.requesttype = USB_RT_HUB | 0x80; + dr.request = USB_REQ_GET_DESCRIPTOR; + dr.value = (USB_DT_HUB << 8); + dr.index = 0; + dr.length = size; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, size); +} + +int usb_clear_port_feature(struct usb_device *dev, int port, int feature) +{ + devrequest dr; + + dr.requesttype = USB_RT_PORT; + dr.request = USB_REQ_CLEAR_FEATURE; + dr.value = feature; + dr.index = port; + dr.length = 0; + + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); +} + +int usb_set_port_feature(struct usb_device *dev, int port, int feature) +{ + devrequest dr; + + dr.requesttype = USB_RT_PORT; + dr.request = USB_REQ_SET_FEATURE; + dr.value = feature; + dr.index = port; + dr.length = 0; + + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); +} + +int usb_get_hub_status(struct usb_device *dev, void *data) +{ + devrequest dr; + + dr.requesttype = USB_RT_HUB | 0x80; + dr.request = USB_REQ_GET_STATUS; + dr.value = 0; + dr.index = 0; + dr.length = 4; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4); +} + +int usb_get_port_status(struct usb_device *dev, int port, void *data) +{ + devrequest dr; + + dr.requesttype = USB_RT_PORT | 0x80; + dr.request = USB_REQ_GET_STATUS; + dr.value = 0; + dr.index = port; + dr.length = 4; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4); +} + +int usb_get_protocol(struct usb_device *dev) +{ + unsigned char buf[8]; + devrequest dr; + + dr.requesttype = USB_RT_HIDD | 0x80; + dr.request = USB_REQ_GET_PROTOCOL; + dr.value = 0; + dr.index = 1; + dr.length = 1; + + if (dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, 1)) + return -1; + + return buf[0]; +} + +int usb_set_protocol(struct usb_device *dev, int protocol) +{ + devrequest dr; + + dr.requesttype = USB_RT_HIDD; + dr.request = USB_REQ_SET_PROTOCOL; + dr.value = protocol; + dr.index = 1; + dr.length = 0; + + if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0)) + return -1; + + return 0; +} + +/* keyboards want a nonzero duration according to HID spec, but + mice should use infinity (0) -keryan */ +int usb_set_idle(struct usb_device *dev, int duration, int report_id) +{ + devrequest dr; + + dr.requesttype = USB_RT_HIDD; + dr.request = USB_REQ_SET_IDLE; + dr.value = (duration << 8) | report_id; + dr.index = 1; + dr.length = 0; + + if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0)) + return -1; + + return 0; +} + +int usb_set_configuration(struct usb_device *dev, int configuration) +{ + devrequest dr; + + dr.requesttype = 0; + dr.request = USB_REQ_SET_CONFIGURATION; + dr.value = configuration; + dr.index = 0; + dr.length = 0; + + if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0)) + return -1; + + return 0; +} + +int usb_get_report(struct usb_device *dev) +{ + unsigned char buf[8]; + devrequest dr; + + dr.requesttype = USB_RT_HIDD | 0x80; + dr.request = USB_REQ_GET_REPORT; + dr.value = 0x100; + dr.index = 1; + dr.length = 3; + + if (dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, 3)) + return -1; + + return buf[0]; +} + +int usb_get_configuration(struct usb_device *dev) +{ + unsigned int size; + unsigned char buffer[400]; + + /* Get the first 8 bytes - guaranteed */ + if (usb_get_descriptor(dev, USB_DT_CONFIG, 0, buffer, 8)) + return -1; + + /* Get the full buffer */ + size = *(unsigned short *)(buffer+2); + if (size > sizeof(buffer)) + { + printk(KERN_INFO "usb: truncated DT_CONFIG (want %d).\n", size); + size = sizeof(buffer); + } + + if (usb_get_descriptor(dev, USB_DT_CONFIG, 0, buffer, size)) + return -1; + + return usb_parse_configuration(dev, buffer, size); +} + +/* + * By the time we get here, the device has gotten a new device ID + * and is in the default state. We need to identify the thing and + * get the ball rolling.. + */ +void usb_new_device(struct usb_device *dev) +{ + int addr, i; + + printk("USB new device connect, assigned device number %d\n", + dev->devnum); + + dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ + + addr = dev->devnum; + dev->devnum = 0; + + /* Slow devices */ + for (i = 0; i < 5; i++) { + if (!usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) + break; + + printk("get_descriptor failed, waiting\n"); + wait_ms(200); + } + if (i == 5) { + printk("giving up\n"); + return; + } + +#if 0 + printk("maxpacketsize: %d\n", dev->descriptor.bMaxPacketSize0); +#endif + switch (dev->descriptor.bMaxPacketSize0) { + case 8: dev->maxpacketsize = 0; break; + case 16: dev->maxpacketsize = 1; break; + case 32: dev->maxpacketsize = 2; break; + case 64: dev->maxpacketsize = 3; break; + } +#if 0 + printk("dev->mps: %d\n", dev->maxpacketsize); +#endif + + dev->devnum = addr; + + if (usb_set_address(dev)) { + printk("Unable to set address\n"); + /* FIXME: We should disable the port */ + return; + } + + wait_ms(10); /* Let the SET_ADDRESS settle */ + + if (usb_get_device_descriptor(dev)) { + printk("Unable to get device descriptor\n"); + return; + } + + if (usb_get_configuration(dev)) { + printk("Unable to get configuration\n"); + return; + } + +#if 0 + printk("Vendor: %X\n", dev->descriptor.idVendor); + printk("Product: %X\n", dev->descriptor.idProduct); +#endif + + usb_device_descriptor(dev); +} + +int usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) +{ + return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id); +} + diff -u --recursive --new-file v2.2.6/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.2.6/linux/drivers/usb/usb.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usb.h Wed Apr 28 11:14:03 1999 @@ -0,0 +1,371 @@ +#ifndef __LINUX_USB_H +#define __LINUX_USB_H + +#include +#include +#include + +static __inline__ void wait_ms(unsigned int ms) +{ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(1 + ms / 10); +} + + +typedef struct { + unsigned char requesttype; + unsigned char request; + unsigned short value; + unsigned short index; + unsigned short length; +} devrequest; + +/* + * Class codes + */ +#define USB_CLASS_HUB 9 + +/* + * Descriptor types + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 + +#define USB_DT_HUB 0x29 +#define USB_DT_HID 0x21 + +/* + * Standard requests + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +/* 0x02 is reserved */ +#define USB_REQ_SET_FEATURE 0x03 +/* 0x04 is reserved */ +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +/* + * HIDD requests + */ +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_GET_IDLE 0x02 +#define USB_REQ_GET_PROTOCOL 0x03 +#define USB_REQ_SET_REPORT 0x09 +#define USB_REQ_SET_IDLE 0x0A +#define USB_REQ_SET_PROTOCOL 0x0B + +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* + * Request target types. + */ +#define USB_RT_DEVICE 0x00 +#define USB_RT_INTERFACE 0x01 +#define USB_RT_ENDPOINT 0x02 + +#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) + +#define USB_RT_HIDD (USB_TYPE_CLASS | USB_RECIP_INTERFACE) + +/* + * USB device number allocation bitmap. There's one bitmap + * per USB tree. + */ +struct usb_devmap { + unsigned long devicemap[128 / (8*sizeof(unsigned long))]; +}; + +/* + * This is a USB device descriptor. + * + * USB device information + * + * Make this MUCH dynamic, right now + * it contains enough information for + * a USB floppy controller, and nothing + * else. + * + * I'm not proud. I just want this dang + * thing to start working. + */ +#define USB_MAXCONFIG 2 +#define USB_MAXINTERFACES 8 +#define USB_MAXENDPOINTS 4 + +struct usb_device_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __u16 idVendor; + __u16 idProduct; + __u16 bcdDevice; + __u8 iManufacturer; + __u8 iProduct; + __u8 iSerialNumber; + __u8 bNumConfigurations; +}; + +/* Endpoint descriptor */ +struct usb_endpoint_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bEndpointAddress; + __u8 bmAttributes; + __u16 wMaxPacketSize; + __u8 bInterval; +}; + +/* Interface descriptor */ +struct usb_interface_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bInterfaceNumber; + __u8 bAlternateSetting; + __u8 bNumEndpoints; + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + __u8 iInterface; + + struct usb_endpoint_descriptor endpoint[USB_MAXENDPOINTS]; +}; + +/* Configuration descriptor information.. */ +struct usb_config_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u16 wTotalLength; + __u8 bNumInterfaces; + __u8 bConfigurationValue; + __u8 iConfiguration; + __u8 bmAttributes; + __u8 MaxPower; + + struct usb_interface_descriptor interface[USB_MAXINTERFACES]; +}; + +/* String descriptor */ +struct usb_string_descriptor { + __u8 bLength; + __u8 bDescriptorType; +}; + +/* Hub descriptor */ +struct usb_hub_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bNbrPorts; + __u16 wHubCharacteristics; + __u8 bPwrOn2PwrGood; + __u8 bHubContrCurrent; + /* DeviceRemovable and PortPwrCtrlMask want to be variable-length + bitmaps that hold max 256 entries, but for now they're ignored */ + __u8 filler; +}; + +struct usb_device; + +struct usb_driver { + const char * name; + int (*probe)(struct usb_device *); + void (*disconnect)(struct usb_device *); + struct list_head driver_list; +}; + +/* + * Pointer to a device endpoint interrupt function -greg + */ +typedef int (*usb_device_irq)(int, void *, void *); + +struct usb_operations { + struct usb_device *(*allocate)(struct usb_device *); + int (*deallocate)(struct usb_device *); + int (*control_msg)(struct usb_device *, unsigned int, void *, void *, int); + int (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *); +}; + +/* + * Allocated per bus we have + */ +struct usb_bus { + struct usb_devmap devmap; /* Device map */ + struct usb_operations *op; /* Operations (specific to the HC) */ + struct usb_device *root_hub; /* Root hub */ + void *hcpriv; /* Host Controller private data */ +}; + + +#define USB_MAXCHILDREN (8) + +struct usb_device { + int devnum; /* Device number on USB bus */ + int slow; /* Slow device? */ + int maxpacketsize; /* Maximum packet size */ + + struct usb_bus *bus; /* Bus we're apart of */ + struct usb_driver *driver; /* Driver */ + struct usb_device_descriptor descriptor; /* Descriptor */ + struct usb_config_descriptor config[USB_MAXCONFIG]; /* All of the configs */ + struct usb_device *parent; + + /* + * Child devices - these can be either new devices + * (if this is a hub device), or different instances + * of this same device. + * + * Each instance needs its own set of data structuctures. + */ + + int maxchild; /* Number of ports if hub */ + struct usb_device *children[USB_MAXCHILDREN]; + + void *hcpriv; /* Host Controller private data */ + void *private; /* Upper layer private data */ +}; + +extern int usb_register(struct usb_driver *); +extern void usb_deregister(struct usb_driver *); + +extern int usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *); + +extern void usb_init_root_hub(struct usb_device *dev); +extern void usb_connect(struct usb_device *dev); +extern void usb_disconnect(struct usb_device **); +extern void usb_device_descriptor(struct usb_device *dev); + +extern int usb_parse_configuration(struct usb_device *dev, void *buf, int len); + +/* + * Calling this entity a "pipe" is glorifying it. A USB pipe + * is something embarrassingly simple: it basically consists + * of the following information: + * - device number (7 bits) + * - endpoint number (4 bits) + * - current Data0/1 state (1 bit) + * - direction (1 bit) + * - speed (1 bit) + * - max packet size (2 bits: 8, 16, 32 or 64) + * - pipe type (2 bits: control, interrupt, bulk, isochronous) + * + * That's 18 bits. Really. Nothing more. And the USB people have + * documented these eighteen bits as some kind of glorious + * virtual data structure. + * + * Let's not fall in that trap. We'll just encode it as a simple + * unsigned int. The encoding is: + * + * - device: bits 8-14 + * - endpoint: bits 15-18 + * - Data0/1: bit 19 + * - direction: bit 7 (0 = Host-to-Device, 1 = Device-to-Host) + * - speed: bit 26 (0 = High, 1 = Low Speed) + * - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64) + * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk) + * + * Why? Because it's arbitrary, and whatever encoding we select is really + * up to us. This one happens to share a lot of bit positions with the UCHI + * specification, so that much of the uhci driver can just mask the bits + * appropriately. + */ + +#define usb_maxpacket(pipe) (8 << ((pipe) & 3)) +#define usb_packetid(pipe) (((pipe) & 0x80) ? 0x69 : 0xE1) + +#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) +#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) +#define usb_pipedata(pipe) (((pipe) >> 19) & 1) +#define usb_pipeout(pipe) (((pipe) & 0x80) == 0) +#define usb_pipeslow(pipe) (((pipe) >> 26) & 1) + +#define usb_pipetype(pipe) (((pipe) >> 30) & 3) +#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == 0) +#define usb_pipeint(pipe) (usb_pipetype((pipe)) == 1) +#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == 2) +#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == 3) + +#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) + +static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint) +{ + return (dev->devnum << 8) | (endpoint << 15) | (dev->slow << 26) | dev->maxpacketsize; +} + +static inline unsigned int __default_pipe(struct usb_device *dev) +{ + return (dev->slow << 26); +} + +/* Create control pipes.. */ +#define usb_sndctrlpipe(dev,endpoint) ((2 << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvctrlpipe(dev,endpoint) ((2 << 30) | __create_pipe(dev,endpoint) | 0x80) +#define usb_snddefctrl(dev) ((2 << 30) | __default_pipe(dev)) +#define usb_rcvdefctrl(dev) ((2 << 30) | __default_pipe(dev) | 0x80) + +/* Create .. */ + +/* + * Send and receive control messages.. + */ +void usb_new_device(struct usb_device *dev); +int usb_set_address(struct usb_device *dev); +int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned +char descindex, void *buf, int size); +int usb_get_device_descriptor(struct usb_device *dev); +int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size); +int usb_clear_port_feature(struct usb_device *dev, int port, int feature); +int usb_set_port_feature(struct usb_device *dev, int port, int feature); +int usb_get_hub_status(struct usb_device *dev, void *data); +int usb_get_port_status(struct usb_device *dev, int port, void *data); +int usb_get_protocol(struct usb_device *dev); +int usb_set_protocol(struct usb_device *dev, int protocol); +int usb_set_idle(struct usb_device *dev, int duration, int report_id); +int usb_set_configuration(struct usb_device *dev, int configuration); +int usb_get_report(struct usb_device *dev); + +/* + * Debugging helpers.. + */ +void usb_show_device_descriptor(struct usb_device_descriptor *); +void usb_show_config_descriptor(struct usb_config_descriptor *); +void usb_show_interface_descriptor(struct usb_interface_descriptor *); +void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *); +void usb_show_hub_descriptor(struct usb_hub_descriptor *); +void usb_show_device(struct usb_device *); + +/* + * Audio parsing helpers + */ + +#ifdef CONFIG_USB_AUDIO +void usb_audio_interface(struct usb_interface_descriptor *, u8 *); +void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *); +#else +extern inline void usb_audio_interface(struct usb_interface_descriptor *, u8 *) {} +extern inline void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *) {} +#endif + +#endif + diff -u --recursive --new-file v2.2.6/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.2.6/linux/drivers/video/atyfb.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/atyfb.c Thu Apr 22 19:30:08 1999 @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.103 1999/03/09 14:01:44 davem Exp $ +/* $Id: atyfb.c,v 1.106 1999/04/16 11:20:49 geert Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -385,7 +385,6 @@ #endif void atyfb_setup(char *options, int *ints); - static int currcon = 0; static struct fb_ops atyfb_ops = { @@ -779,7 +778,8 @@ return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -806,7 +806,8 @@ return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -840,7 +841,8 @@ return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -910,7 +912,8 @@ return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -1644,30 +1647,24 @@ pll_ext_cntl = mpostdiv; /* xclk == mclk */ switch (vclk_post_div) { - case 1: - vpostdiv = 0; - break; case 2: vpostdiv = 1; break; case 3: - vpostdiv = 0; pll_ext_cntl |= 0x10; + case 1: + vpostdiv = 0; break; + case 6: + pll_ext_cntl |= 0x10; case 4: vpostdiv = 2; break; - case 6: - vpostdiv = 2; + case 12: pll_ext_cntl |= 0x10; - break; case 8: vpostdiv = 3; break; - case 12: - vpostdiv = 3; - pll_ext_cntl |= 0x10; - break; } vclk_post_div = vpostdiv; @@ -1690,7 +1687,7 @@ 1, 2, 4, 8, 3, 0, 6, 12 }; - u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 1) | + u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 2) | (vclk_post_div & 3)]; if (vpostdiv == 0) return -EINVAL; @@ -2114,7 +2111,8 @@ if (info->fb_info.changevar) (*info->fb_info.changevar)(con); } - if (con == currcon) + if (!info->fb_info.display_fg || + info->fb_info.display_fg->vc_num == con) atyfb_set_par(&par, info); if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) @@ -2159,7 +2157,7 @@ static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -2178,16 +2176,21 @@ struct fb_info *info) { int err; + struct display *disp; - if (!fb_display[con].cmap.len) { /* no colormap allocated? */ - int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; - if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) + if (con >= 0) + disp = &fb_display[con]; + else + disp = info->disp; + if (!disp->cmap.len) { /* no colormap allocated? */ + int size = disp->var.bits_per_pixel == 16 ? 32 : 256; + if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info); else - fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; } @@ -2198,6 +2201,12 @@ #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; struct fbtype fbtyp; + struct display *disp; + + if (con >= 0) + disp = &fb_display[con]; + else + disp = info->disp; switch (cmd) { case FBIOGTYPE: @@ -2205,7 +2214,7 @@ fbtyp.fb_width = fb->current_par.crtc.vxres; fbtyp.fb_height = fb->current_par.crtc.vyres; fbtyp.fb_depth = fb->current_par.crtc.bpp; - fbtyp.fb_cmsize = fb_display[con].cmap.len; + fbtyp.fb_cmsize = disp->cmap.len; fbtyp.fb_size = fb->total_vram; copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT); break; @@ -2785,7 +2794,7 @@ */ for (i = 0; i < 6 && pdev->base_address[i]; i++) /* nothing */; - j = i + 3; + j = i + 4; info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC); if (!info->mmap_map) { @@ -2813,15 +2822,33 @@ size &= ~1; size = ~(size) + 1; + /* + * Map the framebuffer a second time, this time without + * the braindead _PAGE_IE setting. This is used by the + * fixed Xserver, but we need to maintain the old mapping + * to stay compatible with older ones... + */ + if (base == addr) { + info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK; + info->mmap_map[j].poff = __pa(base & PAGE_MASK); + info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; + info->mmap_map[j].prot_mask = _PAGE_CACHE; + info->mmap_map[j].prot_flag = _PAGE_E; + j++; + } + + /* + * Here comes the old framebuffer mapping with _PAGE_IE + * set for the big endian half of the framebuffer... + */ if (base == addr) { - info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK; - info->mmap_map[j].poff = __pa((base + 0x800000) - & PAGE_MASK); - info->mmap_map[j].size = 0x800000; - info->mmap_map[j].prot_mask = _PAGE_CACHE; - info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; - size -= 0x800000; - j++; + info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK; + info->mmap_map[j].poff = __pa((base+0x800000) & PAGE_MASK); + info->mmap_map[j].size = 0x800000; + info->mmap_map[j].prot_mask = _PAGE_CACHE; + info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; + size -= 0x800000; + j++; } info->mmap_map[j].voff = pbase & PAGE_MASK; @@ -3556,7 +3583,8 @@ #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3578,7 +3606,8 @@ #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3602,7 +3631,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3618,7 +3648,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3633,7 +3664,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3656,7 +3688,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3672,7 +3705,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3687,7 +3721,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3710,7 +3745,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3726,7 +3762,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3741,7 +3778,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3764,7 +3802,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3780,7 +3819,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3795,7 +3835,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif diff -u --recursive --new-file v2.2.6/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c --- v2.2.6/linux/drivers/video/creatorfb.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/creatorfb.c Thu Apr 22 19:30:08 1999 @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.26 1999/03/11 00:29:54 davem Exp $ +/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -718,6 +718,11 @@ i = prom_getintdefault (fb->prom_node, "board_type", 8); sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev); + + /* Elite3D has different DAC revision numbering, and no DAC revisions + have the reversed meaning of cursor enable */ + if (afb) + fb->s.ffb.dac_rev = 10; return idstring; } diff -u --recursive --new-file v2.2.6/linux/drivers/video/fbcon-cfb2.c linux/drivers/video/fbcon-cfb2.c --- v2.2.6/linux/drivers/video/fbcon-cfb2.c Wed Mar 10 15:29:48 1999 +++ linux/drivers/video/fbcon-cfb2.c Wed Apr 28 08:48:45 1999 @@ -50,7 +50,7 @@ void fbcon_cfb2_setup(struct display *p) { - p->next_line = p->var.xres_virtual>>2; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>2; p->next_plane = 0; } diff -u --recursive --new-file v2.2.6/linux/drivers/video/fbcon-cfb4.c linux/drivers/video/fbcon-cfb4.c --- v2.2.6/linux/drivers/video/fbcon-cfb4.c Wed Mar 10 15:29:48 1999 +++ linux/drivers/video/fbcon-cfb4.c Wed Apr 28 08:48:45 1999 @@ -50,7 +50,7 @@ void fbcon_cfb4_setup(struct display *p) { - p->next_line = p->var.xres_virtual>>1; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>1; p->next_plane = 0; } diff -u --recursive --new-file v2.2.6/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c --- v2.2.6/linux/drivers/video/fbcon.c Mon Mar 29 11:09:11 1999 +++ linux/drivers/video/fbcon.c Thu Apr 22 19:30:08 1999 @@ -1700,6 +1700,7 @@ fb_display[i].fontdata && FNTSUM(fb_display[i].fontdata) == k && FNTSIZE(fb_display[i].fontdata) == size && + fontwidth(&fb_display[i]) == w && !memcmp(fb_display[i].fontdata, new_data, size)) { kfree(new_data - FONT_EXTRA_WORDS*sizeof(int)); new_data = fb_display[i].fontdata; @@ -1961,7 +1962,7 @@ /* Return if the frame buffer is not mapped */ if (!fb) return 0; - + /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for * DIRECTCOLOR */ if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) || @@ -2013,6 +2014,9 @@ logo = linux_logo_bw; logo_depth = 1; } + + if (p->fb_info->fbops->fb_rasterimg) + p->fb_info->fbops->fb_rasterimg(p->fb_info, 1); for (x = 0; x < smp_num_cpus * (LOGO_W + 8) && x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) { @@ -2039,12 +2043,18 @@ val = (*src << redshift) | (*src << greenshift) | (*src << blueshift); + if (bdepth == 4 && !((long)dst & 3)) { + /* Some cards require 32bit access */ + *(u32 *)dst = val; + dst += 4; + } else { #ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) + for( i = 0; i < bdepth; ++i ) #else - for( i = bdepth-1; i >= 0; --i ) + for( i = bdepth-1; i >= 0; --i ) #endif - *dst++ = val >> (i*8); + *dst++ = val >> (i*8); + } } } } @@ -2107,12 +2117,18 @@ val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) | safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) | safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift); + if (bdepth == 4 && !((long)dst & 3)) { + /* Some cards require 32bit access */ + *(u32 *)dst = val; + dst += 4; + } else { #ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) + for( i = 0; i < bdepth; ++i ) #else - for( i = bdepth-1; i >= 0; --i ) + for( i = bdepth-1; i >= 0; --i ) #endif - *dst++ = val >> (i*8); + *dst++ = val >> (i*8); + } } } done = 1; @@ -2223,6 +2239,9 @@ #endif } + if (p->fb_info->fbops->fb_rasterimg) + p->fb_info->fbops->fb_rasterimg(p->fb_info, 0); + /* Modes not yet supported: packed pixels with depth != 8 (does such a * thing exist in reality?) */ diff -u --recursive --new-file v2.2.6/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- v2.2.6/linux/drivers/video/fbmem.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/fbmem.c Thu Apr 22 19:30:08 1999 @@ -203,17 +203,24 @@ static int last_fb_vc = MAX_NR_CONSOLES-1; static int fbcon_is_default = 1; -static inline int PROC_CONSOLE(void) +static int PROC_CONSOLE(struct fb_info *info) { + int fgc; + + if (info->display_fg != NULL) + fgc = info->display_fg->vc_num; + else + return -1; + if (!current->tty) - return fg_console; + return fgc; if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) /* XXX Should report error here? */ - return fg_console; + return fgc; if (MINOR(current->tty->device) < 1) - return fg_console; + return fgc; return MINOR(current->tty->device) - 1; } @@ -248,7 +255,7 @@ if (! fb || ! info->disp) return -ENODEV; - fb->fb_get_fix(&fix,PROC_CONSOLE(), info); + fb->fb_get_fix(&fix,PROC_CONSOLE(info), info); base_addr=info->disp->screen_base; copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); if (copy_to_user(buf, base_addr+p, copy_size)) @@ -272,7 +279,7 @@ if (! fb || ! info->disp) return -ENODEV; - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); + fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); base_addr=info->disp->screen_base; copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); if (copy_from_user(base_addr+p, buf, copy_size)) @@ -288,7 +295,7 @@ int unit, err; var->activate |= FB_ACTIVATE_TEST; - err = fb->fb_set_var(var, PROC_CONSOLE(), info); + err = fb->fb_set_var(var, PROC_CONSOLE(info), info); var->activate &= ~FB_ACTIVATE_TEST; if (err) return err; @@ -365,7 +372,7 @@ return -ENODEV; switch (cmd) { case FBIOGET_VSCREENINFO: - if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info))) + if ((i = fb->fb_get_var(&var, PROC_CONSOLE(info), info))) return i; return copy_to_user((void *) arg, &var, sizeof(var)) ? -EFAULT : 0; @@ -374,29 +381,29 @@ return -EFAULT; i = var.activate & FB_ACTIVATE_ALL ? set_all_vcs(fbidx, fb, &var, info) - : fb->fb_set_var(&var, PROC_CONSOLE(), info); + : fb->fb_set_var(&var, PROC_CONSOLE(info), info); if (i) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; return 0; case FBIOGET_FSCREENINFO: - if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info))) + if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(info), info))) return i; return copy_to_user((void *) arg, &fix, sizeof(fix)) ? -EFAULT : 0; case FBIOPUTCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info)); + return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(info), info)); case FBIOGETCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info)); + return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(info), info)); case FBIOPAN_DISPLAY: if (copy_from_user(&var, (void *) arg, sizeof(var))) return -EFAULT; - if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info))) + if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(info), info))) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; @@ -430,7 +437,7 @@ set_con2fb_map(i, con2fb.framebuffer); return 0; default: - return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(), + return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info), info); } } @@ -450,7 +457,7 @@ return -ENODEV; if (fb->fb_mmap) return fb->fb_mmap(info, file, vma); - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); + fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); /* frame buffer memory */ start = (unsigned long)fix.smem_start; @@ -460,7 +467,7 @@ if (vma->vm_offset >= len) { /* memory mapped io */ vma->vm_offset -= len; - fb->fb_get_var(&var, PROC_CONSOLE(), info); + fb->fb_get_var(&var, PROC_CONSOLE(info), info); if (var.accel_flags) return -EINVAL; start = (unsigned long)fix.mmio_start; diff -u --recursive --new-file v2.2.6/linux/drivers/video/leofb.c linux/drivers/video/leofb.c --- v2.2.6/linux/drivers/video/leofb.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/leofb.c Thu Apr 22 19:30:08 1999 @@ -1,7 +1,7 @@ -/* $Id: leofb.c,v 1.5 1999/03/09 14:02:29 davem Exp $ +/* $Id: leofb.c,v 1.6 1999/04/01 13:03:25 jj Exp $ * leofb.c: Leo (ZX) 24/8bit frame buffer driver * - * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) */ @@ -80,12 +80,12 @@ struct leo_lc_ss0_usr { volatile u32 csr; - volatile u32 attrs; - volatile u32 fontc; - volatile u32 fontc2; + volatile u32 addrspace; + volatile u32 fontmsk; + volatile u32 fontt; volatile u32 extent; volatile u32 src; - u32 xxx1[1]; + u32 dst; volatile u32 copy; volatile u32 fill; }; @@ -98,19 +98,42 @@ u8 unknown; }; -struct leo_ld_ss0 { +struct leo_ld { u8 xxx0[0xe00]; - u32 xxx1[2]; - volatile u32 unk; - u32 xxx2[1]; - volatile u32 unk2; - volatile u32 unk3; - u32 xxx3[2]; + volatile u32 csr; + volatile u32 wid; + volatile u32 wmask; + volatile u32 widclip; + volatile u32 vclipmin; + volatile u32 vclipmax; + volatile u32 pickmin; /* SS1 only */ + volatile u32 pickmax; /* SS1 only */ volatile u32 fg; volatile u32 bg; - u8 xxx4[0x05c]; + volatile u32 src; /* Copy/Scroll (SS0 only) */ + volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ + volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ + u32 xxx1[3]; + volatile u32 setsem; /* SS1 only */ + volatile u32 clrsem; /* SS1 only */ + volatile u32 clrpick; /* SS1 only */ + volatile u32 clrdat; /* SS1 only */ + volatile u32 alpha; /* SS1 only */ + u8 xxx2[0x2c]; + volatile u32 winbg; volatile u32 planemask; volatile u32 rop; + volatile u32 z; + volatile u32 dczf; /* SS1 only */ + volatile u32 dczb; /* SS1 only */ + volatile u32 dcs; /* SS1 only */ + volatile u32 dczs; /* SS1 only */ + volatile u32 pickfb; /* SS1 only */ + volatile u32 pickbb; /* SS1 only */ + volatile u32 dcfc; /* SS1 only */ + volatile u32 forcecol; /* SS1 only */ + volatile u32 door[8]; /* SS1 only */ + volatile u32 pick[5]; /* SS1 only */ }; #define LEO_SS1_MISC_ENABLE 0x00000001 @@ -126,17 +149,17 @@ static struct sbus_mmap_map leo_mmap_map[] = { { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 }, - { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, PAGE_SIZE }, - { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, PAGE_SIZE }, - { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, PAGE_SIZE }, + { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 }, + { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 }, + { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 }, { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 }, - { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, PAGE_SIZE }, - { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, PAGE_SIZE }, - { LEO_UNK_MAP, LEO_OFF_UNK, PAGE_SIZE }, - { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, PAGE_SIZE }, - { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, PAGE_SIZE }, - { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, PAGE_SIZE }, - { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, PAGE_SIZE }, + { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 }, + { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 }, + { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 }, + { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 }, + { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 }, + { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 }, + { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 }, { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 }, { 0, 0, 0 } }; @@ -152,19 +175,14 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int x, y, w, h; int i; do { i = us->csr; } while (i & 0x20000000); - ss->unk = 0xffff; - ss->unk2 = 0; - ss->unk3 = fb->s.leo.extent; - ss->fg = (attr_bgcol_ec(p,conp)<<24) | 0x030703; - ss->planemask = 0xff000000; - ss->rop = 0xd0840; + ss->fg = (attr_bgcol_ec(p,conp)<<24); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); } else { @@ -176,9 +194,8 @@ x = sx * fontwidth(p); w = width * fontwidth(p); } us->extent = (w - 1) | ((h - 1) << 11); - i = us->attrs; us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) | - ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + 0x80000000; } static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -186,23 +203,17 @@ { int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; - do { - i = us->csr; - } while (i & 0x20000000); - ss->unk = 0xffff; - ss->unk2 = 0; - ss->unk3 = fb->s.leo.extent; - ss->fg = (attr_bgcol(p,s)<<24) | 0x030703; - ss->planemask = 0xff000000; - ss->rop = 0xd0840; + ss->fg = (attr_bgcol(p,s)<<24); while (count-- > 0) { + do { + i = us->csr; + } while (i & 0x20000000); us->extent = (boxes[2] - boxes[0] - 1) | ((boxes[3] - boxes[1] - 1) << 11); - i = us->attrs; - us->fill = boxes[0] | (boxes[1] << 11) | - ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000; + boxes += 4; } } @@ -210,7 +221,7 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int i, x, y; u8 *fd; u32 *u; @@ -235,11 +246,7 @@ } while (i & 0x20000000); ss->fg = attr_fgcol(p,c) << 24; ss->bg = attr_bgcol(p,c) << 24; - ss->rop = 0x310040; - ss->planemask = 0xff000000; - us->fontc2 = 0xFFFFFFFE; - us->attrs = 4; - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++, u += 2048) @@ -257,7 +264,7 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u32 *u; @@ -267,11 +274,7 @@ } while (i & 0x20000000); ss->fg = attr_fgcol(p,scr_readw(s)) << 24; ss->bg = attr_bgcol(p,scr_readw(s)) << 24; - ss->rop = 0x310040; - ss->planemask = 0xff000000; - us->fontc2 = 0xFFFFFFFE; - us->attrs = 4; - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); if (fontwidthlog(p)) x = (xx << fontwidthlog(p)); else @@ -282,7 +285,7 @@ y = (yy * fontheight(p)) << 11; u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { - us->fontc = 0xFFFFFFFF<<(32-4*fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-4*fontwidth(p)); x = 4*fontwidth(p) - fontheight(p)*2048; while (count >= 4) { count -= 4; @@ -310,7 +313,7 @@ } } } else { - us->fontc = 0xFFFFFFFF<<(32-2*fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-2*fontwidth(p)); x = 2*fontwidth(p) - fontheight(p)*2048; while (count >= 2) { count -= 2; @@ -328,7 +331,7 @@ u += x; } } - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); x = fontwidth(p) - fontheight(p)*2048; while (count) { count--; @@ -457,8 +460,8 @@ fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE; } -__initfunc(static int -leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)) +static int __init +leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl) { struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn; struct fb_wid_item *wi; @@ -476,6 +479,8 @@ lx_krn->krn_type = 0x5800 + j; lx_krn->krn_value = wi->wi_values[0]; } + lx_krn->krn_type = LEO_KRN_TYPE_WID; + lx_krn->krn_csr = 3; return 0; } @@ -484,9 +489,43 @@ p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); } +static void leo_switch_from_graph (struct fb_info_sbusfb *fb) +{ + register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; + register struct leo_ld *ss = fb->s.leo.ld_ss0; + + ss->wid = 0xffffffff; + ss->wmask = 0xffff; + ss->vclipmin = 0; + ss->vclipmax = fb->s.leo.extent; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + ss->widclip = 0; + us->addrspace = 4; + us->fontt = 0; +} + +static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start) +{ + register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; + register struct leo_ld *ss = fb->s.leo.ld_ss0; + + if (start) { + ss->wid = 1; + ss->planemask = 0xffffff; + ss->rop = 0x310b90; + us->addrspace = 0; + } else { + ss->wid = 0xffffffff; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + us->addrspace = 4; + } +} + static char idstring[40] __initdata = { 0 }; -__initfunc(char *leofb_init(struct fb_info_sbusfb *fb)) +char * __init leofb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; @@ -496,44 +535,53 @@ struct fb_wid_item wi; struct fb_wid_list wl; int i; + register struct leo_lc_ss0_usr *us; + register struct leo_ld *ss; + struct fb_ops *fbops; strcpy(fb->info.modename, "Leo"); strcpy(fix->id, "Leo"); - fix->visual = 0xff; /* We only know how to do acceleration and know nothing - about the actual memory layout */ + fix->visual = FB_VISUAL_TRUECOLOR; fix->line_length = 8192; fix->accel = FB_ACCEL_SUN_LEO; + var->bits_per_pixel = 32; + var->green.offset = 8; + var->blue.offset = 16; var->accel_flags = FB_ACCELF_TEXT; + fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); + if (!fbops) return NULL; + + *fbops = *fb->info.fbops; + fbops->fb_rasterimg = leo_rasterimg; + fb->info.fbops = fbops; + disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0, 0x800000, "leo_ram", fb->iospace, 0); disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin; - fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) + us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, - PAGE_SIZE, "leo_lc_ss0_usr", fb->iospace, 0); - fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *) + 0x1000, "leo_lc_ss0_usr", fb->iospace, 0); + ss = fb->s.leo.ld_ss0 = (struct leo_ld *) sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, - PAGE_SIZE, "leo_ld_ss0", fb->iospace, 0); + 0x1000, "leo_ld_ss0", fb->iospace, 0); fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *) sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, - PAGE_SIZE, "leo_ld_ss1", fb->iospace, 0); + 0x1000, "leo_ld_ss1", fb->iospace, 0); fb->s.leo.lx_krn = (struct leo_lx_krn *) sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0, - PAGE_SIZE, "leo_lx_krn", fb->iospace, 0); + 0x1000, "leo_lx_krn", fb->iospace, 0); fb->s.leo.cursor = (struct leo_cursor *) sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0, sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0); fb->dispsw = leo_dispsw; - + fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16); - fb->s.leo.ld_ss0->unk = 0xffff; - fb->s.leo.ld_ss0->unk2 = 0; - fb->s.leo.ld_ss0->unk3 = fb->s.leo.extent; wl.wl_count = 1; wl.wl_list = &wi; wi.wi_type = FB_WID_DBL_8; @@ -546,17 +594,27 @@ wi.wi_index = 2; wi.wi_values [0] = 0x20; leo_wid_put (fb, &wl); + wi.wi_type = FB_WID_DBL_24; + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put (fb, &wl); fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE; - fb->s.leo.ld_ss0->fg = 0x30703; - fb->s.leo.ld_ss0->planemask = 0xff000000; - fb->s.leo.ld_ss0->rop = 0xd0840; - fb->s.leo.lc_ss0_usr->extent = (type->fb_width-1) | ((type->fb_height-1) << 11); - i = fb->s.leo.lc_ss0_usr->attrs; - fb->s.leo.lc_ss0_usr->fill = (0) | ((0) << 11) | ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + ss->wid = 0xffffffff; + ss->wmask = 0xffff; + ss->vclipmin = 0; + ss->vclipmax = fb->s.leo.extent; + ss->fg = 0; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + ss->widclip = 0; + us->extent = (type->fb_width-1) | ((type->fb_height-1) << 11); + us->addrspace = 4; + us->fill = 0x80000000; + us->fontt = 0; do { - i = fb->s.leo.lc_ss0_usr->csr; + i = us->csr; } while (i & 0x20000000); fb->margins = leo_margins; @@ -565,6 +623,7 @@ fb->setcursormap = leo_setcursormap; fb->setcurshape = leo_setcurshape; fb->restore_palette = leo_restore_palette; + fb->switch_from_graph = leo_switch_from_graph; fb->fill = leo_fill; fb->blank = leo_blank; fb->unblank = leo_unblank; diff -u --recursive --new-file v2.2.6/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c --- v2.2.6/linux/drivers/video/matroxfb.c Wed Mar 10 15:29:48 1999 +++ linux/drivers/video/matroxfb.c Tue Apr 20 15:13:00 1999 @@ -4,7 +4,7 @@ * * (c) 1998,1999 Petr Vandrovec * - * Version: 1.9 1999/01/04 + * Version: 1.15 1999/04/19 * * MTRR stuff: 1998 Tom Rini * @@ -24,6 +24,9 @@ * "Daniel Haun" * Testing, hardware cursor fixes * + * "Scott Wood" + * Fixes + * * "Gerd Knorr" * Betatesting * @@ -452,7 +455,7 @@ #define CPMINFO const struct matrox_fb_info* minfo, #define PMINFO minfo, -static inline struct matrox_fb_info* mxinfo(struct display* p) { +static inline struct matrox_fb_info* mxinfo(const struct display* p) { return (struct matrox_fb_info*)p->fb_info; } @@ -474,7 +477,7 @@ #define PMINFO #if 0 -static inline struct matrox_fb_info* mxinfo(struct display* p) { +static inline struct matrox_fb_info* mxinfo(const struct display* p) { return &global_mxinfo; } #endif @@ -2191,7 +2194,7 @@ step = ACCESS_FBINFO(devflags.textstep); offs = yy * p->next_line + xx * step; - attr = attr_fgcol(p,scr_readw(s)) | (attr_bgcol(p,scr_readw(s)) << 4); + attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4); while (count-- > 0) { unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8; if (chr & 0x10000) chr ^= 0x10008; @@ -2395,6 +2398,10 @@ DBG("initMatrox") + if (ACCESS_FBINFO(currcon_display) != p) + return; + if (p->dispsw && p->conp) + fb_con.con_cursor(p->conp, CM_ERASE); p->dispsw_data = NULL; if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) { if (p->type == FB_TYPE_TEXT) { @@ -4274,6 +4281,17 @@ for (i = 0; i < 21; i++) { outTi3026(PMINFO DACseq[i], hw->DACreg[i]); } + if (oldhw) { + outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); + oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); + oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); + oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + } if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) { /* agrhh... setting up PLL is very slow on Millenium... */ /* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */ @@ -5296,7 +5314,7 @@ "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, 230000, &vbG200, "unknown G200 (AGP)"}, @@ -5743,20 +5761,26 @@ } #ifndef MODULE +static int __init initialized = 0; + __initfunc(void matroxfb_init(void)) { DBG("matroxfb_init") -#if defined(CONFIG_FB_OF) -/* Nothing to do, must be called from offb */ -#else - matrox_init(); -#endif + + if (!initialized) { + initialized = 1; + matrox_init(); + } } #if defined(CONFIG_FB_OF) __initfunc(int matrox_of_init(struct device_node *dp)) { DBG("matrox_of_init"); - matrox_init(); + + if (!initialized) { + initialized = 1; + matrox_init(); + } if (!fb_list) return -ENXIO; return 0; } diff -u --recursive --new-file v2.2.6/linux/drivers/video/promcon.c linux/drivers/video/promcon.c --- v2.2.6/linux/drivers/video/promcon.c Fri Apr 16 14:47:31 1999 +++ linux/drivers/video/promcon.c Thu Apr 22 19:30:08 1999 @@ -1,4 +1,4 @@ -/* $Id: promcon.c,v 1.14 1999/03/09 14:02:42 davem Exp $ +/* $Id: promcon.c,v 1.15 1999/04/22 06:35:32 davem Exp $ * Console driver utilizing PROM sun terminal emulation * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) diff -u --recursive --new-file v2.2.6/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c --- v2.2.6/linux/drivers/video/sbusfb.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/sbusfb.c Thu Apr 22 19:30:08 1999 @@ -520,7 +520,7 @@ static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -537,9 +537,14 @@ struct fb_info *info) { int err; + struct display *disp; - if (!fb_display[con].cmap.len) { /* no colormap allocated? */ - if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<= 0) + disp = &fb_display[con]; + else + disp = info->disp; + if (!disp->cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&disp->cmap, 1<var.bits_per_pixel, 0))) return err; } if (con == currcon) { /* current console? */ @@ -552,7 +557,7 @@ } return err; } else - fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; } diff -u --recursive --new-file v2.2.6/linux/fs/adfs/dir.c linux/fs/adfs/dir.c --- v2.2.6/linux/fs/adfs/dir.c Wed Aug 26 11:37:39 1998 +++ linux/fs/adfs/dir.c Fri Apr 23 21:20:37 1999 @@ -280,8 +280,6 @@ unsigned long parent_object_id, dir_object_id; int buffers, pos; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; sb = inode->i_sb; if (filp->f_pos > ADFS_NUM_DIR_ENTRIES + 2) diff -u --recursive --new-file v2.2.6/linux/fs/adfs/namei.c linux/fs/adfs/namei.c --- v2.2.6/linux/fs/adfs/namei.c Tue Jan 20 16:44:58 1998 +++ linux/fs/adfs/namei.c Fri Apr 23 21:20:37 1999 @@ -98,22 +98,22 @@ return 0; } -int adfs_lookup (struct inode *dir, struct dentry *dentry) +struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry) { struct inode *inode = NULL; struct adfs_idir_entry de; unsigned long ino; if (dentry->d_name.len > ADFS_NAME_LEN) - return -ENAMETOOLONG; + return ERR_PTR(-ENAMETOOLONG); if (adfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de)) { ino = de.inode_no; inode = iget (dir->i_sb, ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); - return 0; + return NULL; } diff -u --recursive --new-file v2.2.6/linux/fs/affs/dir.c linux/fs/affs/dir.c --- v2.2.6/linux/fs/affs/dir.c Wed Aug 26 11:37:39 1998 +++ linux/fs/affs/dir.c Fri Apr 23 21:20:37 1999 @@ -90,9 +90,6 @@ pr_debug("AFFS: readdir(ino=%lu,f_pos=%lu)\n",inode->i_ino,(unsigned long)filp->f_pos); - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; - stored = 0; dir_bh = NULL; fh_bh = NULL; diff -u --recursive --new-file v2.2.6/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.2.6/linux/fs/affs/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/affs/namei.c Fri Apr 23 21:20:37 1999 @@ -201,7 +201,7 @@ return bh; } -int +struct dentry * affs_lookup(struct inode *dir, struct dentry *dentry) { unsigned long ino; @@ -218,11 +218,11 @@ affs_brelse(bh); inode = iget(dir->i_sb,ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } dentry->d_op = &affs_dentry_operations; d_add(dentry,inode); - return 0; + return NULL; } int diff -u --recursive --new-file v2.2.6/linux/fs/autofs/dir.c linux/fs/autofs/dir.c --- v2.2.6/linux/fs/autofs/dir.c Sun Nov 8 14:03:04 1998 +++ linux/fs/autofs/dir.c Fri Apr 23 21:20:37 1999 @@ -38,10 +38,10 @@ /* * No entries except for "." and "..", both of which are handled by the VFS layer */ -static int autofs_dir_lookup(struct inode *dir, struct dentry * dentry) +static struct dentry *autofs_dir_lookup(struct inode *dir,struct dentry *dentry) { d_add(dentry, NULL); - return 0; + return NULL; } static struct file_operations autofs_dir_operations = { diff -u --recursive --new-file v2.2.6/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.2.6/linux/fs/autofs/root.c Tue Mar 23 14:35:48 1999 +++ linux/fs/autofs/root.c Fri Apr 23 21:20:37 1999 @@ -16,7 +16,7 @@ #include "autofs_i.h" static int autofs_root_readdir(struct file *,void *,filldir_t); -static int autofs_root_lookup(struct inode *,struct dentry *); +static struct dentry *autofs_root_lookup(struct inode *,struct dentry *); static int autofs_root_symlink(struct inode *,struct dentry *,const char *); static int autofs_root_unlink(struct inode *,struct dentry *); static int autofs_root_rmdir(struct inode *,struct dentry *); @@ -209,7 +209,7 @@ NULL, /* d_compare */ }; -static int autofs_root_lookup(struct inode *dir, struct dentry *dentry) +static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi; int oz_mode; @@ -217,11 +217,8 @@ DPRINTK(("autofs_root_lookup: name = ")); autofs_say(dentry->d_name.name,dentry->d_name.len); - if (!S_ISDIR(dir->i_mode)) - return -ENOTDIR; - if (dentry->d_name.len > NAME_MAX) - return -ENOENT; /* File name too long to exist */ + return ERR_PTR(-ENOENT);/* File name too long to exist */ sbi = autofs_sbi(dir->i_sb); @@ -253,7 +250,7 @@ */ if (dentry->d_flags & DCACHE_AUTOFS_PENDING) { if (signal_pending(current)) - return -ERESTARTNOINTR; + return ERR_PTR(-ERESTARTNOINTR); } /* @@ -263,9 +260,9 @@ * be OK for the operations we permit from an autofs. */ if ( dentry->d_inode && list_empty(&dentry->d_hash) ) - return -ENOENT; + return ERR_PTR(-ENOENT); - return 0; + return NULL; } static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname) diff -u --recursive --new-file v2.2.6/linux/fs/buffer.c linux/fs/buffer.c --- v2.2.6/linux/fs/buffer.c Mon Mar 29 11:09:11 1999 +++ linux/fs/buffer.c Tue Apr 27 14:34:41 1999 @@ -486,33 +486,6 @@ remove_from_lru_list(bh); } -static inline void put_last_lru(struct buffer_head * bh) -{ - if (bh) { - struct buffer_head **bhp = &lru_list[bh->b_list]; - - if (bh == *bhp) { - *bhp = bh->b_next_free; - return; - } - - if(bh->b_dev == B_FREE) - panic("Wrong block for lru list"); - - /* Add to back of free list. */ - remove_from_lru_list(bh); - if(!*bhp) { - *bhp = bh; - (*bhp)->b_prev_free = bh; - } - - bh->b_next_free = *bhp; - bh->b_prev_free = (*bhp)->b_prev_free; - (*bhp)->b_prev_free->b_next_free = bh; - (*bhp)->b_prev_free = bh; - } -} - static inline void put_last_free(struct buffer_head * bh) { if (bh) { @@ -726,8 +699,6 @@ bh = get_hash_table(dev, block, size); if (bh) { if (!buffer_dirty(bh)) { - if (buffer_uptodate(bh)) - put_last_lru(bh); bh->b_flushtime = 0; } return bh; @@ -833,6 +804,7 @@ /* If dirty, mark the time this buffer should be written back. */ set_writetime(buf, 0); refile_buffer(buf); + touch_buffer(buf); if (buf->b_count) { buf->b_count--; @@ -854,6 +826,7 @@ return; } buf->b_count = 0; + buf->b_state = 0; remove_from_queues(buf); put_last_free(buf); } @@ -867,7 +840,6 @@ struct buffer_head * bh; bh = getblk(dev, block, size); - touch_buffer(bh); if (buffer_uptodate(bh)) return bh; ll_rw_block(READ, 1, &bh); @@ -904,7 +876,6 @@ bh = getblk(dev, block, bufsize); index = BUFSIZE_INDEX(bh->b_size); - touch_buffer(bh); if (buffer_uptodate(bh)) return(bh); else ll_rw_block(READ, 1, &bh); @@ -1525,13 +1496,27 @@ * Use gfp() for the hash table to decrease TLB misses, use * SLAB cache for buffer heads. */ -void __init buffer_init(void) +void __init buffer_init(unsigned long memory_size) { - int order = 5; /* Currently maximum order.. */ + int order; unsigned int nr_hash; - nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct buffer_head *); - hash_table = (struct buffer_head **) __get_free_pages(GFP_ATOMIC, order); + /* we need to guess at the right sort of size for a buffer cache. + the heuristic from working with large databases and getting + fsync times (ext2) manageable, is the following */ + + memory_size >>= 20; + for (order = 5; (1UL << order) < memory_size; order++); + + /* try to allocate something until we get it or we're asking + for something that is really too small */ + + do { + nr_hash = (1UL << order) * PAGE_SIZE / + sizeof(struct buffer_head *); + hash_table = (struct buffer_head **) + __get_free_pages(GFP_ATOMIC, order); + } while (hash_table == NULL && --order > 4); if (!hash_table) panic("Failed to allocate buffer hash table\n"); diff -u --recursive --new-file v2.2.6/linux/fs/coda/dir.c linux/fs/coda/dir.c --- v2.2.6/linux/fs/coda/dir.c Fri Apr 16 14:47:31 1999 +++ linux/fs/coda/dir.c Fri Apr 23 21:20:37 1999 @@ -29,7 +29,7 @@ /* dir inode-ops */ static int coda_create(struct inode *dir, struct dentry *new, int mode); static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev); -static int coda_lookup(struct inode *dir, struct dentry *target); +static struct dentry *coda_lookup(struct inode *dir, struct dentry *target); static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, struct dentry *entry); static int coda_unlink(struct inode *dir_inode, struct dentry *entry); @@ -107,7 +107,7 @@ /* inode operations for directories */ /* acces routines: lookup, readlink, permission */ -static int coda_lookup(struct inode *dir, struct dentry *entry) +static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) { struct coda_inode_info *dircnp; struct inode *res_inode = NULL; @@ -125,16 +125,9 @@ if ( length > CODA_MAXNAMLEN ) { printk("name too long: lookup, %s (%*s)\n", coda_f2s(&dircnp->c_fid), length, name); - return -ENAMETOOLONG; + return ERR_PTR(-ENAMETOOLONG); } - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("coda_lookup: inode is NULL or not a directory\n"); - return -ENOTDIR; - } - - CDEBUG(D_INODE, "name %s, len %d in ino %ld, fid %s\n", name, length, dir->i_ino, coda_f2s(&dircnp->c_fid)); @@ -160,11 +153,11 @@ } error = coda_cnode_make(&res_inode, &resfid, dir->i_sb); if (error) - return error; + return ERR_PTR(error); } else if (error != -ENOENT) { CDEBUG(D_INODE, "error for %s(%*s)%d\n", coda_f2s(&dircnp->c_fid), length, name, error); - return error; + return ERR_PTR(error); } CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n", name, coda_f2s(&resfid), type, error, dropme); @@ -178,7 +171,7 @@ ITOC(res_inode)->c_flags |= C_VATTR; } EXIT; - return 0; + return NULL; } @@ -236,11 +229,6 @@ CDEBUG(D_INODE, "name: %s, length %d, mode %o\n",name, length, mode); - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("coda_create: inode is null or not a directory\n"); - return -ENOENT; - } - if (coda_isroot(dir) && coda_iscontrol(name, length)) return -EPERM; @@ -286,11 +274,6 @@ CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",name, length, mode, rdev); - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("coda_mknod: inode is null or not a directory\n"); - return -ENOENT; - } - if (coda_isroot(dir) && coda_iscontrol(name, length)) return -EPERM; @@ -332,11 +315,6 @@ ENTRY; coda_vfs_stat.mkdir++; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("coda_mkdir: inode is NULL or not a directory\n"); - return -ENOENT; - } - if (coda_isroot(dir) && coda_iscontrol(name, len)) return -EPERM; @@ -490,10 +468,6 @@ ENTRY; coda_vfs_stat.rmdir++; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("coda_rmdir: inode is NULL or not a directory\n"); - return -ENOENT; - } dircnp = ITOC(dir); if (!list_empty(&de->d_hash)) @@ -571,11 +545,6 @@ ENTRY; coda_vfs_stat.readdir++; - - if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) { - printk("coda_readdir: inode is NULL or not a directory\n"); - return -EBADF; - } cnp = ITOC(inode); if ( !cnp->c_ovp ) { diff -u --recursive --new-file v2.2.6/linux/fs/dcache.c linux/fs/dcache.c --- v2.2.6/linux/fs/dcache.c Tue Mar 23 14:35:48 1999 +++ linux/fs/dcache.c Sun Apr 25 23:17:56 1999 @@ -471,8 +471,12 @@ */ void shrink_dcache_memory(int priority, unsigned int gfp_mask) { - if (gfp_mask & __GFP_IO) - prune_dcache(0); + if (gfp_mask & __GFP_IO) { + int count = 0; + if (priority) + count = dentry_stat.nr_unused / priority; + prune_dcache(count); + } } #define NAME_ALLOC_LEN(len) ((len+16) & ~15) diff -u --recursive --new-file v2.2.6/linux/fs/devpts/root.c linux/fs/devpts/root.c --- v2.2.6/linux/fs/devpts/root.c Mon Oct 5 13:13:42 1998 +++ linux/fs/devpts/root.c Fri Apr 23 21:20:37 1999 @@ -17,7 +17,7 @@ #include "devpts_i.h" static int devpts_root_readdir(struct file *,void *,filldir_t); -static int devpts_root_lookup(struct inode *,struct dentry *); +static struct dentry *devpts_root_lookup(struct inode *,struct dentry *); static int devpts_revalidate(struct dentry *); static struct file_operations devpts_root_operations = { @@ -81,9 +81,6 @@ off_t nr; char numbuf[16]; - if (!inode || !S_ISDIR(inode->i_mode)) - return -ENOTDIR; - nr = filp->f_pos; switch(nr) @@ -131,42 +128,39 @@ return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode ); } -static int devpts_root_lookup(struct inode * dir, struct dentry * dentry) +static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * dentry) { struct devpts_sb_info *sbi = SBI(dir->i_sb); unsigned int entry; int i; const char *p; - if (!S_ISDIR(dir->i_mode)) - return -ENOTDIR; - dentry->d_inode = NULL; /* Assume failure */ dentry->d_op = &devpts_dentry_operations; if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) { entry = 0; } else if ( dentry->d_name.len < 1 ) { - return 0; + return NULL; } else { p = dentry->d_name.name; if ( *p < '1' || *p > '9' ) - return 0; + return NULL; entry = *p++ - '0'; for ( i = dentry->d_name.len-1 ; i ; i-- ) { unsigned int nentry = *p++ - '0'; if ( nentry > 9 ) - return 0; + return NULL; nentry += entry * 10; if (nentry < entry) - return 0; + return NULL; entry = nentry; } } if ( entry >= sbi->max_ptys ) - return 0; + return NULL; dentry->d_inode = sbi->inodes[entry]; if ( dentry->d_inode ) @@ -174,5 +168,5 @@ d_add(dentry, dentry->d_inode); - return 0; + return NULL; } diff -u --recursive --new-file v2.2.6/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v2.2.6/linux/fs/ext2/dir.c Thu Nov 12 16:21:22 1998 +++ linux/fs/ext2/dir.c Fri Apr 23 21:20:37 1999 @@ -115,8 +115,6 @@ int err; struct inode *inode = filp->f_dentry->d_inode; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; sb = inode->i_sb; stored = 0; diff -u --recursive --new-file v2.2.6/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.2.6/linux/fs/ext2/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ext2/namei.c Fri Apr 23 21:20:37 1999 @@ -168,14 +168,14 @@ return NULL; } -int ext2_lookup(struct inode * dir, struct dentry *dentry) +struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry) { struct inode * inode; struct ext2_dir_entry_2 * de; struct buffer_head * bh; if (dentry->d_name.len > EXT2_NAME_LEN) - return -ENAMETOOLONG; + return ERR_PTR(-ENAMETOOLONG); bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); inode = NULL; @@ -185,10 +185,10 @@ inode = iget(dir->i_sb, ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); - return 0; + return NULL; } /* diff -u --recursive --new-file v2.2.6/linux/fs/fat/dir.c linux/fs/fat/dir.c --- v2.2.6/linux/fs/fat/dir.c Wed Aug 26 11:37:40 1998 +++ linux/fs/fat/dir.c Fri Apr 23 21:20:37 1999 @@ -9,6 +9,7 @@ * * VFAT extensions by Gordon Chaffee * Merged with msdos fs by Henrik Storner + * Plugged buffer overrun in readdir(). AV */ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) @@ -59,6 +60,7 @@ * characters are a sort of uuencoded 16 bit Unicode value. This lets * us do a full dump and restore of Unicode filenames. We could get * into some trouble with long Unicode names, but ignore that right now. + * Ahem... Stack smashing in ring 0 isn't fun. Fixed. */ static int uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate, @@ -93,6 +95,11 @@ *op++ = '?'; } } + /* We have some slack there, so it's OK */ + if (op>ascii+256) { + op = ascii + 256; + break; + } } *op = 0; return (op - ascii); @@ -138,8 +145,6 @@ unsigned char *unicode = NULL; struct nls_table *nls = MSDOS_SB(sb)->nls_io; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; /* Fake . and .. for the root directory. */ if (inode->i_ino == MSDOS_ROOT_INO) { while (oldpos < 2) { @@ -186,9 +191,17 @@ id = ds->id; if (id & 0x40) { slots = id & ~0x40; - long_slots = slots; - is_long = 1; - alias_checksum = ds->alias_checksum; + /* + * Dirty, but not dirtier than the original, + * and plugs the hole. + */ + if (slots > 20) + slots = 0; + else { + long_slots = slots; + is_long = 1; + alias_checksum = ds->alias_checksum; + } } get_new_entry = 1; diff -u --recursive --new-file v2.2.6/linux/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c --- v2.2.6/linux/fs/fat/fatfs_syms.c Wed May 20 19:10:40 1998 +++ linux/fs/fat/fatfs_syms.c Tue Apr 20 14:37:10 1999 @@ -54,6 +54,7 @@ EXPORT_SYMBOL(unlock_fat); EXPORT_SYMBOL(fat_dir_ioctl); EXPORT_SYMBOL(fat_readpage); +EXPORT_SYMBOL(fat_is_binary); int init_fat_fs(void) { diff -u --recursive --new-file v2.2.6/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.2.6/linux/fs/fat/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/fat/inode.c Fri Apr 23 21:20:37 1999 @@ -332,7 +332,6 @@ fat_brelse (sb, bh); goto out_no_bread; } - set_blocksize(sb->s_dev, blksize); /* * The DOS3 partition size limit is *not* 32M as many people think. @@ -423,6 +422,7 @@ || !b->secs_track || !b->heads; } fat_brelse(sb, bh); + set_blocksize(sb->s_dev, blksize); /* This must be done after the brelse because the bh is a dummy allocated by fat_bread (see buffer.c) @@ -703,8 +703,8 @@ if(raw_entry->attr & ATTR_SYS) if (MSDOS_SB(sb)->options.sys_immutable) inode->i_flags |= S_IMMUTABLE; - MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(sb)->options.conversion, - raw_entry->ext); + MSDOS_I(inode)->i_binary = + fat_is_binary(MSDOS_SB(sb)->options.conversion, raw_entry->ext); MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; diff -u --recursive --new-file v2.2.6/linux/fs/fat/misc.c linux/fs/fat/misc.c --- v2.2.6/linux/fs/fat/misc.c Fri Jan 23 18:10:32 1998 +++ linux/fs/fat/misc.c Tue Apr 20 14:37:10 1999 @@ -51,11 +51,11 @@ /* - * is_binary selects optional text conversion based on the conversion mode and - * the extension part of the file name. + * fat_is_binary selects optional text conversion based on the conversion mode + * and the extension part of the file name. */ -int is_binary(char conversion,char *extension) +int fat_is_binary(char conversion,char *extension) { char *walk; diff -u --recursive --new-file v2.2.6/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c --- v2.2.6/linux/fs/hfs/dir_cap.c Sun Nov 8 14:03:06 1998 +++ linux/fs/hfs/dir_cap.c Fri Apr 23 21:20:37 1999 @@ -27,7 +27,7 @@ /*================ Forward declarations ================*/ -static int cap_lookup(struct inode *, struct dentry *); +static struct dentry *cap_lookup(struct inode *, struct dentry *); static int cap_readdir(struct file *, void *, filldir_t); /*================ Global variables ================*/ @@ -147,7 +147,7 @@ * inode corresponding to an entry in a directory, given the inode for * the directory and the name (and its length) of the entry. */ -static int cap_lookup(struct inode * dir, struct dentry *dentry) +static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry) { ino_t dtype; struct hfs_name cname; @@ -155,10 +155,6 @@ struct hfs_cat_key key; struct inode *inode = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { - return -ENOENT; - } - dentry->d_op = &hfs_dentry_operations; entry = HFS_I(dir)->entry; dtype = HFS_ITYPE(dir->i_ino); @@ -207,7 +203,7 @@ done: d_add(dentry, inode); - return 0; + return NULL; } /* diff -u --recursive --new-file v2.2.6/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c --- v2.2.6/linux/fs/hfs/dir_dbl.c Sun Nov 8 14:03:06 1998 +++ linux/fs/hfs/dir_dbl.c Fri Apr 23 21:20:37 1999 @@ -23,7 +23,7 @@ /*================ Forward declarations ================*/ -static int dbl_lookup(struct inode *, struct dentry *); +static struct dentry *dbl_lookup(struct inode *, struct dentry *); static int dbl_readdir(struct file *, void *, filldir_t); static int dbl_create(struct inode *, struct dentry *, int); static int dbl_mkdir(struct inode *, struct dentry *, int); @@ -130,17 +130,13 @@ * the inode for the directory and the name (and its length) of the * entry. */ -static int dbl_lookup(struct inode * dir, struct dentry *dentry) +static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry) { struct hfs_name cname; struct hfs_cat_entry *entry; struct hfs_cat_key key; struct inode *inode = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { - return -ENOENT; - } - dentry->d_op = &hfs_dentry_operations; entry = HFS_I(dir)->entry; @@ -173,7 +169,7 @@ done: d_add(dentry, inode); - return 0; + return NULL; } /* diff -u --recursive --new-file v2.2.6/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c --- v2.2.6/linux/fs/hfs/dir_nat.c Sun Nov 8 14:03:06 1998 +++ linux/fs/hfs/dir_nat.c Fri Apr 23 21:20:37 1999 @@ -29,7 +29,7 @@ /*================ Forward declarations ================*/ -static int nat_lookup(struct inode *, struct dentry *); +static struct dentry *nat_lookup(struct inode *, struct dentry *); static int nat_readdir(struct file *, void *, filldir_t); static int nat_rmdir(struct inode *, struct dentry *); static int nat_hdr_unlink(struct inode *, struct dentry *); @@ -136,7 +136,7 @@ * the inode corresponding to an entry in a directory, given the inode * for the directory and the name (and its length) of the entry. */ -static int nat_lookup(struct inode * dir, struct dentry *dentry) +static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry) { ino_t dtype; struct hfs_name cname; @@ -144,10 +144,6 @@ struct hfs_cat_key key; struct inode *inode = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { - return -ENOENT; - } - dentry->d_op = &hfs_dentry_operations; entry = HFS_I(dir)->entry; dtype = HFS_ITYPE(dir->i_ino); @@ -199,7 +195,7 @@ done: d_add(dentry, inode); - return 0; + return NULL; } /* diff -u --recursive --new-file v2.2.6/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- v2.2.6/linux/fs/hpfs/hpfs_fs.c Fri Oct 9 13:27:14 1998 +++ linux/fs/hpfs/hpfs_fs.c Fri Apr 23 21:20:38 1999 @@ -192,7 +192,7 @@ size_t count, loff_t *ppos); static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir); -static int hpfs_lookup(struct inode *, struct dentry *); +static struct dentry *hpfs_lookup(struct inode *, struct dentry *); static const struct file_operations hpfs_dir_ops = { @@ -1119,7 +1119,7 @@ * the boondocks.) */ -static int hpfs_lookup(struct inode *dir, struct dentry *dentry) +static struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry) { const char *name = dentry->d_name.name; int len = dentry->d_name.len; @@ -1129,14 +1129,6 @@ int retval; struct quad_buffer_head qbh; - /* In case of madness */ - - retval = -ENOTDIR; - if (dir == 0) - goto out; - if (!S_ISDIR(dir->i_mode)) - goto out; - /* * Read in the directory entry. "." is there under the name ^A^A . * Always read the dir even for . and .. in case we need the dates. @@ -1208,7 +1200,7 @@ brelse4(&qbh); out: - return retval; + return ERR_PTR(retval); } /* @@ -1373,11 +1365,6 @@ char * tempname; long old_pos; struct inode *inode = filp->f_dentry->d_inode; - - if (inode == 0 - || inode->i_sb == 0 - || !S_ISDIR(inode->i_mode)) - return -EBADF; tempname = (char *) __get_free_page(GFP_KERNEL); if (!tempname) diff -u --recursive --new-file v2.2.6/linux/fs/inode.c linux/fs/inode.c --- v2.2.6/linux/fs/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/inode.c Mon Apr 26 13:56:49 1999 @@ -359,10 +359,8 @@ found = 1; } - if (found) { + if (found) dispose_list(freeable); - found = 1; /* silly compiler */ - } return found; } @@ -750,7 +748,7 @@ * Initialize the hash tables and default * value for max inodes */ -#define MAX_INODE (12288) +#define MAX_INODE (16384) void __init inode_init(void) { diff -u --recursive --new-file v2.2.6/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v2.2.6/linux/fs/isofs/dir.c Thu Nov 12 16:21:22 1998 +++ linux/fs/isofs/dir.c Fri Apr 23 21:20:38 1999 @@ -295,9 +295,6 @@ struct iso_directory_record * tmpde; struct inode *inode = filp->f_dentry->d_inode; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; - tmpname = (char *) __get_free_page(GFP_KERNEL); if (!tmpname) return -ENOMEM; diff -u --recursive --new-file v2.2.6/linux/fs/isofs/namei.c linux/fs/isofs/namei.c --- v2.2.6/linux/fs/isofs/namei.c Tue Jan 19 11:32:52 1999 +++ linux/fs/isofs/namei.c Fri Apr 23 21:20:38 1999 @@ -228,7 +228,7 @@ return retval; } -int isofs_lookup(struct inode * dir, struct dentry * dentry) +struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry) { unsigned long ino; struct buffer_head * bh; @@ -237,12 +237,6 @@ #ifdef DEBUG printk("lookup: %x %s\n",dir->i_ino, dentry->d_name.name); #endif - if (!dir) - return -ENOENT; - - if (!S_ISDIR(dir->i_mode)) - return -ENOENT; - dentry->d_op = dir->i_sb->s_root->d_op; bh = isofs_find_entry(dir, dentry, &ino); @@ -253,8 +247,8 @@ inode = iget(dir->i_sb,ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); - return 0; + return NULL; } diff -u --recursive --new-file v2.2.6/linux/fs/minix/dir.c linux/fs/minix/dir.c --- v2.2.6/linux/fs/minix/dir.c Thu Nov 12 16:21:22 1998 +++ linux/fs/minix/dir.c Fri Apr 23 21:20:38 1999 @@ -68,8 +68,6 @@ struct minix_sb_info * info; struct inode *inode = filp->f_dentry->d_inode; - if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) - return -EBADF; info = &inode->i_sb->u.minix_sb; if (filp->f_pos & (info->s_dirsize - 1)) return -EBADF; diff -u --recursive --new-file v2.2.6/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.2.6/linux/fs/minix/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/minix/inode.c Sat Apr 24 12:45:37 1999 @@ -38,14 +38,13 @@ minix_free_inode(inode); } -static void minix_commit_super (struct super_block * sb, - struct minix_super_block * ms) +static void minix_commit_super(struct super_block * sb) { mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); sb->s_dirt = 0; } -static void minix_write_super (struct super_block * sb) +static void minix_write_super(struct super_block * sb) { struct minix_super_block * ms; @@ -54,7 +53,7 @@ if (ms->s_state & MINIX_VALID_FS) ms->s_state &= ~MINIX_VALID_FS; - minix_commit_super (sb, ms); + minix_commit_super(sb); } sb->s_dirt = 0; } @@ -106,7 +105,7 @@ ms->s_state = sb->u.minix_sb.s_mount_state; mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); sb->s_dirt = 1; - minix_commit_super (sb, ms); + minix_commit_super(sb); } else { /* Mount a partition which is read-only, read-write. */ diff -u --recursive --new-file v2.2.6/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v2.2.6/linux/fs/minix/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/minix/namei.c Fri Apr 23 21:20:38 1999 @@ -116,7 +116,7 @@ 0 /* compare */ }; -int minix_lookup(struct inode * dir, struct dentry *dentry) +struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry) { struct inode * inode = NULL; struct minix_dir_entry * de; @@ -132,10 +132,10 @@ inode = iget(dir->i_sb, ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); - return 0; + return NULL; } /* @@ -221,8 +221,6 @@ struct buffer_head * bh; struct minix_dir_entry * de; - if (!dir) - return -ENOENT; inode = minix_new_inode(dir); if (!inode) return -ENOSPC; @@ -251,8 +249,6 @@ struct buffer_head * bh; struct minix_dir_entry * de; - if (!dir) - return -ENOENT; bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { @@ -298,8 +294,6 @@ struct minix_dir_entry * de; struct minix_sb_info * info; - if (!dir || !dir->i_sb) - return -EINVAL; info = &dir->i_sb->u.minix_sb; bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); diff -u --recursive --new-file v2.2.6/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v2.2.6/linux/fs/msdos/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/msdos/namei.c Fri Apr 23 21:20:38 1999 @@ -250,7 +250,7 @@ /***** Get inode using directory and name */ -int msdos_lookup(struct inode *dir,struct dentry *dentry) +struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry) { struct super_block *sb = dir->i_sb; struct inode *inode = NULL; @@ -292,7 +292,7 @@ d_add(dentry, inode); res = 0; out: - return res; + return ERR_PTR(res); } @@ -713,7 +713,7 @@ fat_cache_inval_inode(old_inode); old_inode->i_version = ++event; MSDOS_I(old_inode)->i_binary = - is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext); + fat_is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext); old_inode->i_ino = free_ino; fat_mark_buffer_dirty(sb, free_bh, 1); old_de->name[0] = DELETED_FLAG; diff -u --recursive --new-file v2.2.6/linux/fs/namei.c linux/fs/namei.c --- v2.2.6/linux/fs/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/namei.c Fri Apr 23 21:20:38 1999 @@ -263,12 +263,11 @@ struct dentry * dentry = d_alloc(parent, name); result = ERR_PTR(-ENOMEM); if (dentry) { - int error = dir->i_op->lookup(dir, dentry); - result = dentry; - if (error) { + result = dir->i_op->lookup(dir, dentry); + if (result) dput(dentry); - result = ERR_PTR(error); - } + else + result = dentry; } } up(&dir->i_sem); diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/Config.in linux/fs/ncpfs/Config.in --- v2.2.6/linux/fs/ncpfs/Config.in Sun Jul 26 11:57:18 1998 +++ linux/fs/ncpfs/Config.in Tue Apr 20 15:17:20 1999 @@ -6,5 +6,10 @@ bool ' Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG bool ' Use NFS namespace if available' CONFIG_NCPFS_NFS_NS bool ' Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS +if [ "$CONFIG_NCPFS_OS2_NS" = "y" ]; then + bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS +fi bool ' Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR # bool ' NDS interserver authentication support' CONFIG_NCPFS_NDS_DOMAINS +bool ' Use Native Language Support' CONFIG_NCPFS_NLS +bool ' Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/Makefile linux/fs/ncpfs/Makefile --- v2.2.6/linux/fs/ncpfs/Makefile Thu Jul 16 18:09:28 1998 +++ linux/fs/ncpfs/Makefile Tue Apr 20 15:17:20 1999 @@ -9,7 +9,7 @@ O_TARGET := ncpfs.o O_OBJS := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ - ncpsign_kernel.o + symlink.o ncpsign_kernel.o M_OBJS := $(O_TARGET) # If you want debugging output, please uncomment the following line diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v2.2.6/linux/fs/ncpfs/dir.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ncpfs/dir.c Mon Apr 26 09:26:55 1999 @@ -4,6 +4,7 @@ * Copyright (C) 1995, 1996 by Volker Lendecke * Modified for big endian by J.F. Chadima and David S. Miller * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS * */ @@ -22,6 +23,7 @@ #include #include + #include "ncplib_kernel.h" struct ncp_dirent { @@ -48,13 +50,16 @@ static int ncp_readdir(struct file *, void *, filldir_t); static int ncp_create(struct inode *, struct dentry *, int); -static int ncp_lookup(struct inode *, struct dentry *); +static struct dentry *ncp_lookup(struct inode *, struct dentry *); static int ncp_unlink(struct inode *, struct dentry *); static int ncp_mkdir(struct inode *, struct dentry *, int); static int ncp_rmdir(struct inode *, struct dentry *); static int ncp_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); - +#ifdef CONFIG_NCPFS_EXTRAS +extern int ncp_symlink(struct inode *, struct dentry *, const char *); +#endif + static struct file_operations ncp_dir_operations = { NULL, /* lseek - default */ @@ -77,7 +82,11 @@ ncp_lookup, /* lookup */ NULL, /* link */ ncp_unlink, /* unlink */ +#ifdef CONFIG_NCPFS_EXTRAS + ncp_symlink, /* symlink */ +#else NULL, /* symlink */ +#endif ncp_mkdir, /* mkdir */ ncp_rmdir, /* rmdir */ NULL, /* mknod */ @@ -191,14 +200,6 @@ } } -/* Here we encapsulate the inode number handling that depends upon the - * mount mode: When we mount a complete server, the memory address of - * the ncp_inode_info is used as the inode number. When only a single - * volume is mounted, then the dirEntNum is used as the inode - * number. As this is unique for the complete volume, this should - * enable the NFS exportability of a ncpfs-mounted volume. - */ - /* * Generate a unique inode number. */ @@ -253,37 +254,30 @@ ncp_force_unlink(struct inode *dir, struct dentry* dentry) { int res=0x9c,res2; - struct iattr ia; + struct nw_modify_dos_info info; + __u32 old_nwattr; + struct inode *inode; + memset(&info, 0, sizeof(info)); + /* remove the Read-Only flag on the NW server */ + inode = dentry->d_inode; - memset(&ia,0,sizeof(struct iattr)); - ia.ia_mode = dentry->d_inode->i_mode; - ia.ia_mode |= NCP_SERVER(dir)->m.file_mode & 0222; /* set write bits */ - ia.ia_valid = ATTR_MODE; - - res2=ncp_notify_change(dentry, &ia); - if (res2) - { - goto leave_me; - } + old_nwattr = NCP_FINFO(inode)->nwattr; + info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) + goto leave_me; /* now try again the delete operation */ - res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); if (res) /* delete failed, set R bit again */ { - memset(&ia,0,sizeof(struct iattr)); - ia.ia_mode = dentry->d_inode->i_mode; - ia.ia_mode &= ~(NCP_SERVER(dir)->m.file_mode & 0222); /* clear write bits */ - ia.ia_valid = ATTR_MODE; - - res2=ncp_notify_change(dentry, &ia); - if (res2) - { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) goto leave_me; - } } leave_me: return(res); @@ -293,63 +287,58 @@ #ifdef CONFIG_NCPFS_STRONG static int ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, - struct inode *new_dir, struct dentry* new_dentry, char *_new_name, - int *done_flag) + struct inode *new_dir, struct dentry* new_dentry, char *_new_name) { + struct nw_modify_dos_info info; int res=0x90,res2; - struct iattr ia; + struct inode *old_inode = old_dentry->d_inode; + __u32 old_nwattr = NCP_FINFO(old_inode)->nwattr; + __u32 new_nwattr = 0; /* shut compiler warning */ + int old_nwattr_changed = 0; + int new_nwattr_changed = 0; + memset(&info, 0, sizeof(info)); + /* remove the Read-Only flag on the NW server */ - memset(&ia,0,sizeof(struct iattr)); - ia.ia_mode = old_dentry->d_inode->i_mode; - if (S_ISDIR(ia.ia_mode)) - goto leave_me; - ia.ia_mode |= NCP_SERVER(old_dir)->m.file_mode & 0222; /* set write bits */ - ia.ia_valid = ATTR_MODE; - - res2=ncp_notify_change(old_dentry, &ia); - if (res2) - { - goto leave_me; - } - + info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + if (!res2) + old_nwattr_changed = 1; + if (new_dentry && new_dentry->d_inode) { + new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr; + info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + if (!res2) + new_nwattr_changed = 1; + } /* now try again the rename operation */ - res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), - old_dir, _old_name, - new_dir, _new_name); - - if (!res) { - ncp_invalid_dir_cache(old_dir); - ncp_invalid_dir_cache(new_dir); - d_move(old_dentry,new_dentry); - *done_flag=1; - - if (!old_dentry->d_inode) { - DPRINTK(KERN_INFO "ncpfs: no inode -- file remains rw\n"); - goto leave_me; - } - if ((res2=ncp_lookup_validate(old_dentry))) { - DPRINTK(KERN_DEBUG "ncpfs: ncp_lookup_validate returned %d\n",res2); - } - } - - memset(&ia,0,sizeof(struct iattr)); - ia.ia_mode = old_dentry->d_inode->i_mode; - ia.ia_mode &= ~(NCP_SERVER(old_dentry->d_inode)->m.file_mode & 0222); /* clear write bits */ - ia.ia_valid = ATTR_MODE; - - DPRINTK(KERN_INFO "calling ncp_notify_change() with %s/%s\n", - old_dentry->d_parent->d_name.name,old_dentry->d_name.name); - - res2=ncp_notify_change(old_dentry, &ia); - if (res2) - { - printk(KERN_INFO "ncpfs: ncp_notify_change (2) failed: %08x\n",res2); - /* goto leave_me; */ - } - - leave_me: + /* but only if something really happened */ + if (new_nwattr_changed || old_nwattr_changed) { + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + old_dir, _old_name, + new_dir, _new_name); + } + if (res) + goto leave_me; + /* file was successfully renamed, so: + do not set attributes on old file - it no longer exists + copy attributes from old file to new */ + new_nwattr_changed = old_nwattr_changed; + new_nwattr = old_nwattr; + old_nwattr_changed = 0; + +leave_me:; + if (old_nwattr_changed) { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + /* ignore errors */ + } + if (new_nwattr_changed) { + info.attributes = new_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + /* ignore errors */ + } return(res); } #endif /* CONFIG_NCPFS_STRONG */ @@ -386,11 +375,6 @@ printk(KERN_DEBUG "ncp_lookup_validate: %s, len %d\n", __name, len); #endif - if (!ncp_preserve_case(dir)) { - str_lower(__name); - down_case = 1; - } - /* If the file is in the dir cache, we do not have to ask the server. */ @@ -400,17 +384,14 @@ #endif if (ncp_is_server_root(dir)) { - str_upper(__name); + io2vol(server, __name, 1); down_case = 1; res = ncp_lookup_volume(server, __name, &(finfo.nw_info.i)); } else { - if (!ncp_preserve_case(dir)) - { - str_upper(__name); - down_case = 1; - } + down_case = !ncp_preserve_case(dir); + io2vol(server, __name, down_case); res = ncp_obtain_info(server, dir, __name, &(finfo.nw_info.i)); } @@ -429,6 +410,9 @@ else printk(KERN_DEBUG "ncp_lookup_validate: found, but dirEntNum changed\n"); #endif + vol2io(server, finfo.nw_info.i.entryName, + !ncp_preserve_entry_case(dir, + finfo.nw_info.i.NSCreator)); ncp_update_inode2(dentry->d_inode, &finfo.nw_info); } if (!val) ncp_invalid_dir_cache(dir); @@ -456,11 +440,6 @@ DDPRINTK(KERN_DEBUG "ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n", inode->i_ino, c_ino); - result = -EBADF; - if (!inode || !S_ISDIR(inode->i_mode)) { - printk(KERN_WARNING "ncp_readdir: inode is NULL or not a directory\n"); - goto out; - } result = -EIO; if (!ncp_conn_valid(server)) goto out; @@ -535,10 +514,11 @@ c_last_returned_index = 0; index = 0; - if (!ncp_preserve_case(inode)) { - for (i = 0; i < c_size; i++) { - str_lower(c_entry[i].i.entryName); - } + for (i = 0; i < c_size; i++) + { + vol2io(server, c_entry[i].i.entryName, + !ncp_preserve_entry_case(inode, + c_entry[i].i.NSCreator)); } } } @@ -730,7 +710,7 @@ struct dentry* dent; result = -ENOENT; - str_upper(server->m.mounted_vol); + io2vol(server, server->m.mounted_vol, 1); if (ncp_lookup_volume(server, server->m.mounted_vol, &(server->root.finfo.i)) != 0) { #ifdef NCPFS_PARANOIA @@ -738,7 +718,7 @@ #endif goto out; } - str_lower(server->root.finfo.i.entryName); + vol2io(server, server->root.finfo.i.entryName, 1); dent = server->root_dentry; if (dent) { struct inode* ino = dent->d_inode; @@ -759,7 +739,7 @@ return result; } -static int ncp_lookup(struct inode *dir, struct dentry *dentry) +static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry) { struct ncp_server *server; struct inode *inode = NULL; @@ -769,11 +749,6 @@ struct ncpfs_inode_info finfo; __u8 __name[dentry->d_name.len + 1]; - error = -ENOENT; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk(KERN_WARNING "ncp_lookup: inode is NULL or not a directory.\n"); - goto finished; - } server = NCP_SERVER(dir); error = -EIO; @@ -786,11 +761,6 @@ printk(KERN_DEBUG "ncp_lookup: %s, len %d\n", __name, len); #endif - if (!ncp_preserve_case(dir)) { - str_lower(__name); - down_case = 1; - } - /* If the file is in the dir cache, we do not have to ask the server. */ @@ -830,17 +800,14 @@ #endif if (ncp_is_server_root(dir)) { - str_upper(__name); + io2vol(server, __name, 1); down_case = 1; res = ncp_lookup_volume(server, __name, &(finfo.nw_info.i)); } else { - if (!ncp_preserve_case(dir)) - { - str_upper(__name); - down_case = 1; - } + down_case = !ncp_preserve_case(dir); + io2vol(server, __name, down_case); res = ncp_obtain_info(server, dir, __name, &(finfo.nw_info.i)); } @@ -851,8 +818,11 @@ /* * If we didn't find an entry, make a negative dentry. */ - if (res != 0) + if (res != 0) { goto add_entry; + } else vol2io(server, finfo.nw_info.i.entryName, + !ncp_preserve_entry_case(dir, + finfo.nw_info.i.NSCreator)); } /* @@ -874,7 +844,7 @@ #ifdef NCPFS_PARANOIA printk(KERN_DEBUG "ncp_lookup: result=%d\n", error); #endif - return error; + return ERR_PTR(error); } /* @@ -906,20 +876,17 @@ goto out; } -static int ncp_create(struct inode *dir, struct dentry *dentry, int mode) +int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, + int attributes) { int error, result; struct ncpfs_inode_info finfo; __u8 _name[dentry->d_name.len + 1]; - + #ifdef NCPFS_PARANOIA -printk(KERN_DEBUG "ncp_create: creating %s/%s, mode=%x\n", +printk(KERN_DEBUG "ncp_create_new: creating %s/%s, mode=%x\n", dentry->d_parent->d_name.name, dentry->d_name.name, mode); #endif - if (!dir || !S_ISDIR(dir->i_mode)) { - printk(KERN_WARNING "ncp_create: inode is NULL or not a directory\n"); - return -ENOENT; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(dir))) goto out; @@ -927,14 +894,12 @@ strncpy(_name, dentry->d_name.name, dentry->d_name.len); _name[dentry->d_name.len] = '\0'; - if (!ncp_preserve_case(dir)) { - str_upper(_name); - } + io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir)); error = -EACCES; result = ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name, OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, - 0, AR_READ | AR_WRITE, &finfo.nw_info); + attributes, AR_READ | AR_WRITE, &finfo.nw_info); if (!result) { finfo.nw_info.access = O_RDWR; error = ncp_instantiate(dir, dentry, &finfo); @@ -948,6 +913,11 @@ return error; } +static int ncp_create(struct inode *dir, struct dentry *dentry, int mode) +{ + return ncp_create_new(dir, dentry, mode, 0); +} + static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int error; @@ -956,20 +926,13 @@ DPRINTK(KERN_DEBUG "ncp_mkdir: making %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk(KERN_WARNING "ncp_mkdir: inode is NULL or not a directory\n"); - goto out; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(dir))) goto out; strncpy(_name, dentry->d_name.name, dentry->d_name.len); _name[dentry->d_name.len] = '\0'; - if (!ncp_preserve_case(dir)) { - str_upper(_name); - } + io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir)); error = -EACCES; if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name, @@ -989,13 +952,6 @@ DPRINTK(KERN_DEBUG "ncp_rmdir: removing %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - - error = -ENOENT; - if (!dir || !S_ISDIR(dir->i_mode)) - { - printk(KERN_WARNING "ncp_rmdir: inode is NULL or not a directory\n"); - goto out; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(dir))) @@ -1008,17 +964,34 @@ strncpy(_name, dentry->d_name.name, dentry->d_name.len); _name[dentry->d_name.len] = '\0'; - if (!ncp_preserve_case(dir)) - { - str_upper(_name); - } - error = -EACCES; + io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir)); result = ncp_del_file_or_subdir(NCP_SERVER(dir), dir, _name); - if (!result) - { - ncp_invalid_dir_cache(dir); - error = 0; - } + switch (result) { + case 0x00: + ncp_invalid_dir_cache(dir); + error = 0; + break; + case 0x85: /* unauthorized to delete file */ + case 0x8A: /* unauthorized to delete file */ + error = -EACCES; + break; + case 0x8F: + case 0x90: /* read only */ + error = -EPERM; + break; + case 0x9F: /* in use by another client */ + error = -EBUSY; + break; + case 0xA0: /* directory not empty */ + error = -ENOTEMPTY; + break; + case 0xFF: /* someone deleted file */ + error = -ENOENT; + break; + default: + error = -EACCES; + break; + } out: return error; } @@ -1031,11 +1004,6 @@ DPRINTK(KERN_DEBUG "ncp_unlink: unlinking %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk(KERN_WARNING "ncp_unlink: inode is NULL or not a directory\n"); - goto out; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(dir))) goto out; @@ -1052,19 +1020,38 @@ error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); #ifdef CONFIG_NCPFS_STRONG + /* 9C is Invalid path.. It should be 8F, 90 - read only, but + it is not :-( */ if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */ error = ncp_force_unlink(dir, dentry); } #endif - if (!error) { - DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n", - dentry->d_parent->d_name.name, dentry->d_name.name); - ncp_invalid_dir_cache(dir); - d_delete(dentry); - } else if (error == 0xFF) { - error = -ENOENT; - } else { - error = -EACCES; + switch (error) { + case 0x00: + DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n", + dentry->d_parent->d_name.name, dentry->d_name.name); + ncp_invalid_dir_cache(dir); + d_delete(dentry); + break; + case 0x85: + case 0x8A: + error = -EACCES; + break; + case 0x8D: /* some files in use */ + case 0x8E: /* all files in use */ + error = -EBUSY; + break; + case 0x8F: /* some read only */ + case 0x90: /* all read only */ + case 0x9C: /* !!! returned when in-use or read-only by NW4 */ + error = -EPERM; + break; + case 0xFF: + error = -ENOENT; + break; + default: + error = -EACCES; + break; } out: @@ -1076,7 +1063,7 @@ { int old_len = old_dentry->d_name.len; int new_len = new_dentry->d_name.len; - int error, done_flag=0; + int error; char _old_name[old_dentry->d_name.len + 1]; char _new_name[new_dentry->d_name.len + 1]; @@ -1084,59 +1071,44 @@ old_dentry->d_parent->d_name.name, old_dentry->d_name.name, new_dentry->d_parent->d_name.name, new_dentry->d_name.name); - error = -ENOTDIR; - if (!old_dir || !S_ISDIR(old_dir->i_mode)) { - printk(KERN_WARNING "ncp_rename: old inode is NULL or not a directory\n"); - goto out; - } - if (!new_dir || !S_ISDIR(new_dir->i_mode)) { - printk(KERN_WARNING "ncp_rename: new inode is NULL or not a directory\n"); - goto out; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(old_dir))) goto out; strncpy(_old_name, old_dentry->d_name.name, old_len); _old_name[old_len] = '\0'; - if (!ncp_preserve_case(old_dir)) { - str_upper(_old_name); - } + io2vol(NCP_SERVER(old_dir), _old_name, !ncp_preserve_case(old_dir)); strncpy(_new_name, new_dentry->d_name.name, new_len); _new_name[new_len] = '\0'; - if (!ncp_preserve_case(new_dir)) { - str_upper(_new_name); - } + io2vol(NCP_SERVER(new_dir), _new_name, !ncp_preserve_case(new_dir)); error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), old_dir, _old_name, new_dir, _new_name); #ifdef CONFIG_NCPFS_STRONG - if (error == 0x90 && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */ + if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */ error = ncp_force_rename(old_dir, old_dentry, _old_name, - new_dir, new_dentry, _new_name, - &done_flag); + new_dir, new_dentry, _new_name); } #endif - if (error == 0) - { - if (done_flag == 0) /* if 1, the following already happened */ - { /* in ncp_force_rename() */ - DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n", + switch (error) { + case 0x00: + DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n", old_dentry->d_name.name,new_dentry->d_name.name); - ncp_invalid_dir_cache(old_dir); - ncp_invalid_dir_cache(new_dir); - if (!S_ISDIR(old_dentry->d_inode->i_mode)) - d_move(old_dentry,new_dentry); - } - } else { - if (error == 0x9E) + ncp_invalid_dir_cache(old_dir); + ncp_invalid_dir_cache(new_dir); + /* d_move(old_dentry, new_dentry); */ + break; + case 0x9E: error = -ENAMETOOLONG; - else if (error == 0xFF) + break; + case 0xFF: error = -ENOENT; - else + break; + default: error = -EACCES; + break; } out: return error; @@ -1155,14 +1127,12 @@ static int utc2local(int time) { - return time - sys_tz.tz_minuteswest * 60 + - (sys_tz.tz_dsttime ? 3600 : 0); + return time - sys_tz.tz_minuteswest * 60; } static int local2utc(int time) { - return time + sys_tz.tz_minuteswest * 60 - - (sys_tz.tz_dsttime ? 3600 : 0); + return time + sys_tz.tz_minuteswest * 60; } /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ @@ -1171,7 +1141,9 @@ { int month, year, secs; - month = ((date >> 5) & 15) - 1; + /* first subtract and mask after that... Otherwise, if + date == 0, bad things happen */ + month = ((date >> 5) - 1) & 15; year = date >> 9; secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.2.6/linux/fs/ncpfs/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ncpfs/inode.c Tue Apr 20 15:17:20 1999 @@ -4,6 +4,7 @@ * Copyright (C) 1995, 1996 by Volker Lendecke * Modified for big endian by J.F. Chadima and David S. Miller * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS * */ @@ -27,6 +28,7 @@ #include #include + #include "ncplib_kernel.h" static void ncp_read_inode(struct inode *); @@ -49,6 +51,10 @@ }; extern struct dentry_operations ncp_dentry_operations; +#ifdef CONFIG_NCPFS_EXTRAS +extern struct inode_operations ncp_symlink_inode_operations; +extern int ncp_symlink(struct inode*, struct dentry*, const char*); +#endif static struct nw_file_info *read_nwinfo = NULL; static struct semaphore read_sem = MUTEX; @@ -62,6 +68,12 @@ NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber; +#ifdef CONFIG_NCPFS_SMALLDOS + NCP_FINFO(inode)->origNS = nwinfo->i.NSCreator; +#endif +#ifdef CONFIG_NCPFS_STRONG + NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; +#endif NCP_FINFO(inode)->opened = nwinfo->opened; NCP_FINFO(inode)->access = nwinfo->access; NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle; @@ -79,12 +91,42 @@ struct ncp_server *server = NCP_SERVER(inode); if (!NCP_FINFO(inode)->opened) { +#ifdef CONFIG_NCPFS_STRONG + NCP_FINFO(inode)->nwattr = nwi->attributes; +#endif if (nwi->attributes & aDIR) { inode->i_mode = server->m.dir_mode; inode->i_size = 512; } else { inode->i_mode = server->m.file_mode; inode->i_size = le32_to_cpu(nwi->dataStreamSize); +#ifdef CONFIG_NCPFS_EXTRAS + if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) { + switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { + case aHIDDEN: + if (server->m.flags & NCP_MOUNT_SYMLINKS) { + if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE) + && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) { + inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; + break; + } + } + /* FALLTHROUGH */ + case 0: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= 0444; + break; + case aSYSTEM: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= (inode->i_mode >> 2) & 0111; + break; + /* case aSYSTEM|aHIDDEN: */ + default: + /* reserved combination */ + break; + } + } +#endif } if (nwi->attributes & aRONLY) inode->i_mode &= ~0222; } @@ -114,6 +156,34 @@ } else { inode->i_mode = server->m.file_mode; inode->i_size = le32_to_cpu(nwi->dataStreamSize); +#ifdef CONFIG_NCPFS_EXTRAS + if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) + && (nwi->attributes & aSHARED)) { + switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { + case aHIDDEN: + if (server->m.flags & NCP_MOUNT_SYMLINKS) { + if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE) + && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) { + inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; + break; + } + } + /* FALLTHROUGH */ + case 0: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= 0444; + break; + case aSYSTEM: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= (inode->i_mode >> 2) & 0111; + break; + /* case aSYSTEM|aHIDDEN: */ + default: + /* reserved combination */ + break; + } + } +#endif } if (nwi->attributes & aRONLY) inode->i_mode &= ~0222; @@ -157,6 +227,10 @@ inode->i_op = &ncp_file_inode_operations; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ncp_dir_inode_operations; +#ifdef CONFIG_NCPFS_EXTRAS + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &ncp_symlink_inode_operations; +#endif } else { inode->i_op = NULL; } @@ -211,7 +285,6 @@ { struct ncp_inode_info *root = &(server->root); struct nw_info_struct *i = &(root->finfo.i); - unsigned short dummy; DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i); @@ -219,15 +292,13 @@ i->dataStreamSize= 1024; i->dirEntNum = 0; i->DosDirNum = 0; +#ifdef CONFIG_NCPFS_SMALLDOS + i->NSCreator = NW_NS_DOS; +#endif i->volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */ - ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); - ncp_date_unix2dos(0, &(i->modifyTime ), &(i->modifyDate)); - ncp_date_unix2dos(0, &(dummy ), &(i->lastAccessDate)); - i->creationTime = le16_to_cpu(i->creationTime); - i->creationDate = le16_to_cpu(i->creationDate); - i->modifyTime = le16_to_cpu(i->modifyTime); - i->modifyDate = le16_to_cpu(i->modifyDate); - i->lastAccessDate= le16_to_cpu(i->lastAccessDate); + /* set dates of mountpoint to Jan 1, 1986; 00:00 */ + i->creationTime = i->modifyTime = cpu_to_le16(0x0000); + i->creationDate = i->modifyDate = i->lastAccessDate = cpu_to_le16(0x0C21); i->nameLen = 0; i->entryName[0] = '\0'; @@ -264,8 +335,6 @@ lock_super(sb); - sb->s_flags |= MS_ODD_RENAME; /* This should go away */ - sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; @@ -310,6 +379,14 @@ server->m.dir_mode = (server->m.dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; +#ifdef CONFIG_NCPFS_NLS + /* load the default NLS charsets */ + server->nls_charsets.codepage[0] = 0; + server->nls_charsets.iocharset[0] = 0; + server->nls_vol = load_nls_default(); + server->nls_io = load_nls_default(); +#endif /* CONFIG_NCPFS_NLS */ + server->packet_size = NCP_PACKET_SIZE; server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL); if (server->packet == NULL) @@ -379,6 +456,10 @@ out_no_packet: printk(KERN_ERR "ncp_read_super: could not alloc packet\n"); out_free_server: +#ifdef CONFIG_NCPFS_NLS + unload_nls(server->nls_io); + unload_nls(server->nls_vol); +#endif ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); goto out_unlock; out_no_server: @@ -418,6 +499,20 @@ ncp_disconnect(server); ncp_unlock_server(server); +#ifdef CONFIG_NCPFS_NLS + /* unload the NLS charsets */ + if (server->nls_vol) + { + unload_nls(server->nls_vol); + server->nls_vol = NULL; + } + if (server->nls_io) + { + unload_nls(server->nls_io); + server->nls_io = NULL; + } +#endif /* CONFIG_NCPFS_NLS */ + fput(server->ncp_filp); kill_proc(server->m.wdog_pid, SIGTERM, 1); @@ -459,9 +554,12 @@ int result = 0; int info_mask; struct nw_modify_dos_info info; + struct ncp_server *server; result = -EIO; - if (!ncp_conn_valid(NCP_SERVER(inode))) + + server = NCP_SERVER(inode); + if ((!server) || !ncp_conn_valid(server)) goto out; result = inode_change_ok(inode, attr); @@ -470,11 +568,11 @@ result = -EPERM; if (((attr->ia_valid & ATTR_UID) && - (attr->ia_uid != NCP_SERVER(inode)->m.uid))) + (attr->ia_uid != server->m.uid))) goto out; if (((attr->ia_valid & ATTR_GID) && - (attr->ia_gid != NCP_SERVER(inode)->m.gid))) + (attr->ia_gid != server->m.gid))) goto out; if (((attr->ia_valid & ATTR_MODE) && @@ -488,26 +586,53 @@ #if 1 if ((attr->ia_valid & ATTR_MODE) != 0) { - if (!S_ISREG(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) { + umode_t newmode; + + info_mask |= DM_ATTRIBUTES; + newmode = attr->ia_mode; + newmode &= NCP_SERVER(inode)->m.dir_mode; + + if (newmode & 0222) + info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + else + info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + } else if (!S_ISREG(inode->i_mode)) { return -EPERM; } else { umode_t newmode; - +#ifdef CONFIG_NCPFS_EXTRAS + int extras; + + extras = server->m.flags & NCP_MOUNT_EXTRAS; +#endif info_mask |= DM_ATTRIBUTES; newmode=attr->ia_mode; - newmode &= NCP_SERVER(inode)->m.file_mode; +#ifdef CONFIG_NCPFS_EXTRAS + if (!extras) +#endif + newmode &= server->m.file_mode; if (newmode & 0222) /* any write bit set */ { - info.attributes &= ~0x60001; + info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); } else { - info.attributes |= 0x60001; + info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); } +#ifdef CONFIG_NCPFS_EXTRAS + if (extras) { + if (newmode & 0111) /* any execute bit set */ + info.attributes |= aSHARED | aSYSTEM; + /* read for group/world and not in default file_mode */ + else if (newmode & ~server->m.file_mode & 0444) + info.attributes |= aSHARED; + } +#endif } } #endif @@ -548,6 +673,10 @@ result = 0; } } +#ifdef CONFIG_NCPFS_STRONG + if ((!result) && (info_mask & DM_ATTRIBUTES)) + NCP_FINFO(inode)->nwattr = info.attributes; +#endif } if ((attr->ia_valid & ATTR_SIZE) != 0) { int written; diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c --- v2.2.6/linux/fs/ncpfs/ioctl.c Tue Mar 17 22:18:15 1998 +++ linux/fs/ncpfs/ioctl.c Tue Apr 20 15:17:20 1999 @@ -3,6 +3,7 @@ * * Copyright (C) 1995, 1996 by Volker Lendecke * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS * */ @@ -17,6 +18,7 @@ #include #include + #include "ncplib_kernel.h" /* maximum limit for ncp_objectname_ioctl */ @@ -485,6 +487,69 @@ return 0; } #endif /* CONFIG_NCPFS_NDS_DOMAINS */ + +#ifdef CONFIG_NCPFS_NLS +/* Here we are select the iocharset and the codepage for NLS. + * Thanks Petr Vandrovec for idea and many hints. + */ + case NCP_IOC_SETCHARSETS: + if ( (permission(inode, MAY_WRITE) != 0) + && (current->uid != server->m.mounted_uid)) + { + return -EACCES; + } + if (server->root_setuped) return -EBUSY; + { + struct ncp_nls_ioctl user; + struct nls_table *codepage; + struct nls_table *iocharset; + struct nls_table *oldset_io; + struct nls_table *oldset_cp; + + if (copy_from_user(&user, + (struct ncp_nls_ioctl*)arg, + sizeof(user))) return -EFAULT; + + codepage = NULL; + if (!user.codepage[0]) { + codepage = load_nls_default(); + } + else { + codepage = load_nls(user.codepage); + if (! codepage) { + return -EBADRQC; + } + } + + iocharset = NULL; + if (user.iocharset[0] == 0) { + iocharset = load_nls_default(); + } + else { + iocharset = load_nls(user.iocharset); + if (! iocharset) { + unload_nls(codepage); + return -EBADRQC; + } + } + + oldset_cp = server->nls_vol; + server->nls_vol = codepage; + oldset_io = server->nls_io; + server->nls_io = iocharset; + server->nls_charsets = user; + if (oldset_cp) unload_nls(oldset_cp); + if (oldset_io) unload_nls(oldset_io); + return 0; + } + + case NCP_IOC_GETCHARSETS: /* not tested */ + if (copy_to_user((struct ncp_nls_ioctl*)arg, + &(server->nls_charsets), + sizeof(server->nls_charsets))) return -EFAULT; + return 0; +#endif /* CONFIG_NCPFS_NLS */ + default: return -EINVAL; } diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c --- v2.2.6/linux/fs/ncpfs/ncplib_kernel.c Fri Oct 9 13:27:15 1998 +++ linux/fs/ncpfs/ncplib_kernel.c Tue Apr 20 15:17:20 1999 @@ -238,7 +238,8 @@ } static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num, - __u32 dir_base, int have_dir_base, char *path) + __u32 dir_base, int have_dir_base, + const char *path) { ncp_add_byte(server, vol_num); ncp_add_dword(server, dir_base); @@ -468,12 +469,17 @@ target->nameLen = strlen(volname); strcpy(target->entryName, volname); target->attributes = aDIR; + /* set dates to Jan 1, 1986 00:00 */ + target->creationTime = target->modifyTime = cpu_to_le16(0x0000); + target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21); return 0; } -int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, - struct inode *dir, __u32 info_mask, - struct nw_modify_dos_info *info) +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server, + struct inode *dir, + const char *path, + __u32 info_mask, + const struct nw_modify_dos_info *info) { __u8 volnum = NCP_FINFO(dir)->volNumber; __u32 dirent = NCP_FINFO(dir)->dirEntNum; @@ -487,13 +493,22 @@ ncp_add_dword(server, info_mask); ncp_add_mem(server, info, sizeof(*info)); - ncp_add_handle_path(server, volnum, dirent, 1, NULL); + ncp_add_handle_path(server, volnum, dirent, 1, path); result = ncp_request(server, 87); ncp_unlock_server(server); return result; } +int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, + struct inode *dir, + __u32 info_mask, + const struct nw_modify_dos_info *info) +{ + return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL, + info_mask, info); +} + static int ncp_DeleteNSEntry(struct ncp_server *server, __u8 have_dir_base, __u8 volnum, __u32 dirent, @@ -787,6 +802,35 @@ ncp_unlock_server(server); return result; } + +#ifdef CONFIG_NCPFS_EXTRAS +int +ncp_read_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, char *target, int *bytes_read) { + int error; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs(get_ds()); + error = ncp_read(server, file_id, offset, to_read, target, bytes_read); + set_fs(old_fs); + return error; +} + +int +ncp_write_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) { + int error; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs(get_ds()); + error = ncp_write(server, file_id, offset, to_write, source, bytes_written); + set_fs(old_fs); + return error; +} +#endif #ifdef CONFIG_NCPFS_IOCTL_LOCKING int diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h --- v2.2.6/linux/fs/ncpfs/ncplib_kernel.h Tue Mar 10 10:03:34 1998 +++ linux/fs/ncpfs/ncplib_kernel.h Tue Apr 20 15:17:20 1999 @@ -4,6 +4,7 @@ * Copyright (C) 1995, 1996 by Volker Lendecke * Modified for big endian by J.F. Chadima and David S. Miller * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS * */ @@ -23,6 +24,10 @@ #include #include +#ifdef CONFIG_NCPFS_NLS +#include +#endif + #include #include #include @@ -36,12 +41,19 @@ int ncp_read(struct ncp_server *, const char *, __u32, __u16, char *, int *); int ncp_write(struct ncp_server *, const char *, __u32, __u16, const char *, int *); +#ifdef CONFIG_NCPFS_EXTRAS +int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, char *, int *); +int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, + const char *, int *); +#endif int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, struct nw_info_struct *target); int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *); int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *, - __u32, struct nw_modify_dos_info *info); + __u32, const struct nw_modify_dos_info *info); +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *, + const char* path, __u32, const struct nw_modify_dos_info *info); int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *); @@ -75,4 +87,83 @@ ncp_mount_subdir(struct ncp_server* server, __u8 volNumber, __u8 srcNS, __u32 srcDirEntNum); #endif /* CONFIG_NCPFS_MOUNT_SUBDIR */ + +#ifdef CONFIG_NCPFS_NLS +/* This are the NLS conversion routines with inspirations and code parts + * from the vfat file system and hints from Petr Vandrovec. + */ + +/* + * It should be replaced by charset specifc conversion. Gordon Chaffee + * has prepared some things, but I don't know, what he thinks about it. + * The conversion tables for the io charsets should be generatable by + * Unicode table, shouldn't it? I have written so generation code for it. + * The tables for the vendor specific codepages...? Hmm. The Samba sources + * contains also any hints. + */ + +#define toupperif(c, u) ((((u) != 0) && ((c) >= 'a') && ((c) <= 'z')) \ + ? (c)-('a'-'A') : (c)) +#define tolowerif(c, u) ((((u) != 0) && ((c) >= 'A') && ((c) <= 'Z')) \ + ? (c)-('A'-'a') : (c)) + +static inline void +io2vol(struct ncp_server *server, char *name, int case_trans) +{ + unsigned char nc; + unsigned char *np; + unsigned char *up; + struct nls_unicode uc; + struct nls_table *nls_in; + struct nls_table *nls_out; + + nls_in = server->nls_io; + nls_out = server->nls_vol; + np = name; + + while (*np) + { + nc = 0; + uc = nls_in->charset2uni[toupperif(*np, case_trans)]; + up = nls_out->page_uni2charset[uc.uni2]; + if (up != NULL) nc = up[uc.uni1]; + if (nc != 0) *np = nc; + np++; + } +} + +static inline void +vol2io(struct ncp_server *server, char *name, int case_trans) +{ + unsigned char nc; + unsigned char *np; + unsigned char *up; + struct nls_unicode uc; + struct nls_table *nls_in; + struct nls_table *nls_out; + + nls_in = server->nls_vol; + nls_out = server->nls_io; + np = name; + + while (*np) + { + nc = 0; + uc = nls_in->charset2uni[*np]; + up = nls_out->page_uni2charset[uc.uni2]; + if (up != NULL) nc = up[uc.uni1]; + if (nc == 0) nc = *np; + *np = tolowerif(nc, case_trans); + np++; + } +} + +#else + +#define io2vol(S,N,U) if (U) str_upper(N) +#define vol2io(S,N,U) if (U) str_lower(N) + +#endif /* CONFIG_NCPFS_NLS */ + #endif /* _NCPLIB_H */ + diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/symlink.c linux/fs/ncpfs/symlink.c --- v2.2.6/linux/fs/ncpfs/symlink.c Wed Dec 31 16:00:00 1969 +++ linux/fs/ncpfs/symlink.c Tue Apr 20 15:17:20 1999 @@ -0,0 +1,212 @@ +/* + * linux/fs/ncpfs/symlink.c + * + * Code for allowing symbolic links on NCPFS (i.e. NetWare) + * Symbolic links are not supported on native NetWare, so we use an + * infrequently-used flag (Sh) and store a two-word magic header in + * the file to make sure we don't accidentally use a non-link file + * as a link. + * + * from linux/fs/ext2/symlink.c + * + * Copyright (C) 1998-99, Frank A. Vorstenbosch + * + * ncpfs symlink handling code + * NLS support (c) 1999 Petr Vandrovec + * + */ + +#include + +#ifdef CONFIG_NCPFS_EXTRAS + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "ncplib_kernel.h" + + +/* these magic numbers must appear in the symlink file -- this makes it a bit + more resilient against the magic attributes being set on random files. */ + +#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */ +#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e) + +static int ncp_readlink(struct dentry *, char *, int); +static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int); +int ncp_create_new(struct inode *dir, struct dentry *dentry, + int mode,int attributes); + +/* + * symlinks can't do much... + */ +struct inode_operations ncp_symlink_inode_operations={ + NULL, /* no file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + ncp_readlink, /* readlink */ + ncp_follow_link, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; + +/* ----- follow a symbolic link ------------------------------------------ */ + +static struct dentry *ncp_follow_link(struct dentry *dentry, + struct dentry *base, + unsigned int follow) +{ + struct inode *inode=dentry->d_inode; + int error, length, cnt; + char *link; + +#ifdef DEBUG + printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow); +#endif + + if(!S_ISLNK(inode->i_mode)) { + dput(base); + return ERR_PTR(-EINVAL); + } + + if(ncp_make_open(inode,O_RDONLY)) { + dput(base); + return ERR_PTR(-EIO); + } + + for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) { + if (cnt > 10) { + dput(base); + return ERR_PTR(-EAGAIN); /* -ENOMEM? */ + } + schedule(); + } + + error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, + 0,NCP_MAX_SYMLINK_SIZE,link,&length); + + if (error!=0 || lengthd_inode; + char *link; + int length,error; + +#ifdef DEBUG + printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen); +#endif + + if(!S_ISLNK(inode->i_mode)) + return -EINVAL; + + if(ncp_make_open(inode,O_RDONLY)) + return -EIO; + + if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL) + return -ENOMEM; + + error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, + 0,NCP_MAX_SYMLINK_SIZE,link,&length); + + if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) || + ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) { + error = -EIO; + goto out; + } + + link[length] = 0; + + vol2io(NCP_SERVER(inode), link+8, 0); + + error = length - 8; + if(copy_to_user(buffer, link+8, error)) + error = -EFAULT; + +out:; + kfree(link); + return error; +} + +/* ----- create a new symbolic link -------------------------------------- */ + +int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { + int i,length; + struct inode *inode; + char *link; + +#ifdef DEBUG + printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname); +#endif + + if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)) + return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */ + + if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE) + return -EINVAL; + + if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL) + return -ENOMEM; + + if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) { + kfree(link); + return -EIO; + } + + inode=dentry->d_inode; + + ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0; + ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1; + memcpy(link+8, symname, length+1); /* including last zero for io2vol */ + + /* map to/from server charset, do not touch upper/lower case as + symlink can point out of ncp filesystem */ + io2vol(NCP_SERVER(inode), link+8, 0); + + if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + 0, length+8, link, &i) || i!=length+8) { + kfree(link); + return -EIO; + } + + kfree(link); + return 0; +} +#endif + +/* ----- EOF ----- */ diff -u --recursive --new-file v2.2.6/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.2.6/linux/fs/nfs/dir.c Fri Apr 16 14:47:31 1999 +++ linux/fs/nfs/dir.c Sat Apr 24 12:45:37 1999 @@ -51,10 +51,9 @@ static int nfs_safe_remove(struct dentry *); -static int nfs_dir_open(struct inode *, struct file *); static ssize_t nfs_dir_read(struct file *, char *, size_t, loff_t *); static int nfs_readdir(struct file *, void *, filldir_t); -static int nfs_lookup(struct inode *, struct dentry *); +static struct dentry *nfs_lookup(struct inode *, struct dentry *); static int nfs_create(struct inode *, struct dentry *, int); static int nfs_mkdir(struct inode *, struct dentry *, int); static int nfs_rmdir(struct inode *, struct dentry *); @@ -73,7 +72,7 @@ NULL, /* select - default */ NULL, /* ioctl - default */ NULL, /* mmap */ - nfs_dir_open, /* open - revalidate */ + NULL, /* no special open is needed */ NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ @@ -102,16 +101,6 @@ nfs_revalidate, /* revalidate */ }; -static int -nfs_dir_open(struct inode *dir, struct file *file) -{ - struct dentry *dentry = file->f_dentry; - - dfprintk(VFS, "NFS: nfs_dir_open(%s/%s)\n", - dentry->d_parent->d_name.name, dentry->d_name.name); - return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry); -} - static ssize_t nfs_dir_read(struct file *filp, char *buf, size_t count, loff_t *ppos) { @@ -147,11 +136,6 @@ dfprintk(VFS, "NFS: nfs_readdir(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); - result = -EBADF; - if (!inode || !S_ISDIR(inode->i_mode)) { - printk("nfs_readdir: inode is NULL or not a directory\n"); - goto out; - } result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry); if (result < 0) @@ -397,7 +381,6 @@ { struct dentry * parent = dentry->d_parent; struct inode * inode = dentry->d_inode; - unsigned long time = jiffies - dentry->d_time; int error; struct nfs_fh fhandle; struct nfs_fattr fattr; @@ -406,31 +389,36 @@ * If we don't have an inode, let's just assume * a 5-second "live" time for negative dentries. */ - if (!inode) { - if (time < NFS_REVALIDATE_INTERVAL) - goto out_valid; - goto out_bad; - } + if (!inode) + goto do_lookup; if (is_bad_inode(inode)) { -#ifdef NFS_PARANOIA -printk("nfs_lookup_validate: %s/%s has dud inode\n", -parent->d_name.name, dentry->d_name.name); -#endif + dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n", + parent->d_name.name, dentry->d_name.name); goto out_bad; } - if (time < NFS_ATTRTIMEO(inode)) + if (_nfs_revalidate_inode(NFS_DSERVER(dentry), dentry)) + goto out_bad; + + if (time_before(jiffies,dentry->d_time+NFS_ATTRTIMEO(inode))) goto out_valid; if (IS_ROOT(dentry)) goto out_valid; +do_lookup: /* * Do a new lookup and check the dentry attributes. */ error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent), dentry->d_name.name, &fhandle, &fattr); + if (dentry->d_inode == NULL) { + if (error == -ENOENT && + time_before(jiffies,dentry->d_time+NFS_REVALIDATE_INTERVAL)) + goto out_valid; + goto out_bad; + } if (error) goto out_bad; @@ -439,8 +427,10 @@ goto out_bad; /* Filehandle matches? */ - if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) - goto out_bad; + if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) { + if (dentry->d_count < 2) + goto out_bad; + } /* Ok, remeber that we successfully checked it.. */ nfs_renew_times(dentry); @@ -449,6 +439,10 @@ out_valid: return 1; out_bad: + if (dentry->d_parent->d_inode) + nfs_invalidate_dircache(dentry->d_parent->d_inode); + if (inode && S_ISDIR(inode->i_mode)) + nfs_invalidate_dircache(inode); return 0; } @@ -533,7 +527,7 @@ } #endif -static int nfs_lookup(struct inode *dir, struct dentry * dentry) +static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry) { struct inode *inode; int error; @@ -579,7 +573,7 @@ } } out: - return error; + return ERR_PTR(error); } /* @@ -764,7 +758,7 @@ { struct qstr sqstr; struct dentry *sdentry; - int error; + struct dentry *res; sqstr.name = silly; sqstr.len = slen; @@ -774,10 +768,10 @@ sdentry = d_alloc(parent, &sqstr); if (sdentry == NULL) return ERR_PTR(-ENOMEM); - error = nfs_lookup(parent->d_inode, sdentry); - if (error) { + res = nfs_lookup(parent->d_inode, sdentry); + if (res) { dput(sdentry); - return ERR_PTR(error); + return res; } } return sdentry; diff -u --recursive --new-file v2.2.6/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.2.6/linux/fs/nfs/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/nfs/inode.c Sat Apr 24 12:45:37 1999 @@ -37,6 +37,8 @@ #define NFS_PARANOIA 1 static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *); +static void nfs_zap_caches(struct inode *); +static void nfs_invalidate_inode(struct inode *); static void nfs_read_inode(struct inode *); static void nfs_put_inode(struct inode *); @@ -234,6 +236,11 @@ server->rsize = nfs_block_size(data->rsize, NULL); server->wsize = nfs_block_size(data->wsize, NULL); server->flags = data->flags; + + if (data->flags & NFS_MOUNT_NOAC) { + data->acregmin = data->acregmax = 0; + data->acdirmin = data->acdirmax = 0; + } server->acregmin = data->acregmin*HZ; server->acregmax = data->acregmax*HZ; server->acdirmin = data->acdirmin*HZ; @@ -388,25 +395,61 @@ * could cause file corruption. But since the dentry * count is 0 and all pending IO for a dentry has been * flushed when the count went to 0, we're safe here. + * Also returns the number of unhashed dentries */ -void nfs_free_dentries(struct inode *inode) +static int +nfs_free_dentries(struct inode *inode) { struct list_head *tmp, *head = &inode->i_dentry; + int unhashed; restart: tmp = head; + unhashed = 0; while ((tmp = tmp->next) != head) { struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); -printk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, -dentry->d_count, !list_empty(&dentry->d_hash)); + dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + dentry->d_count, !list_empty(&dentry->d_hash)); if (!dentry->d_count) { dget(dentry); d_drop(dentry); dput(dentry); goto restart; } + if (!list_empty(&dentry->d_hash)) + unhashed++; } + return unhashed; +} + +/* + * Invalidate the local caches + */ +static void +nfs_zap_caches(struct inode *inode) +{ + NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); + NFS_CACHEINV(inode); + + if (S_ISDIR(inode->i_mode)) + nfs_invalidate_dircache(inode); + else + invalidate_inode_pages(inode); +} + +/* + * Invalidate, but do not unhash, the inode + */ +static void +nfs_invalidate_inode(struct inode *inode) +{ + umode_t save_mode = inode->i_mode; + + make_bad_inode(inode); + inode->i_mode = save_mode; + nfs_inval(inode); + nfs_zap_caches(inode); } /* @@ -508,7 +551,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr) { struct inode *inode; - int max_count; + int max_count, stale_inode, unhashed = 0; retry: inode = iget(sb, fattr->fileid); @@ -527,27 +570,30 @@ * as the inode may have become a different object. * (We can probably handle modes changes here, too.) */ + stale_inode = inode->i_mode && + ((fattr->mode ^ inode->i_mode) & S_IFMT); + stale_inode |= inode->i_count && inode->i_count == unhashed; max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink; - if (inode->i_count > max_count) { -printk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n", -inode->i_ino, inode->i_count, inode->i_nlink); - nfs_free_dentries(inode); - if (inode->i_count > max_count) { -printk("__nfs_fhget: inode %ld still busy, i_count=%d\n", -inode->i_ino, inode->i_count); + if (stale_inode || inode->i_count > max_count + unhashed) { + dprintk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n", + inode->i_ino, inode->i_count, inode->i_nlink); + unhashed = nfs_free_dentries(inode); + if (stale_inode || inode->i_count > max_count + unhashed) { + printk("__nfs_fhget: inode %ld still busy, i_count=%d\n", + inode->i_ino, inode->i_count); if (!list_empty(&inode->i_dentry)) { struct dentry *dentry; dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); -printk("__nfs_fhget: killing %s/%s filehandle\n", -dentry->d_parent->d_name.name, dentry->d_name.name); - memset(dentry->d_fsdata, 0, + printk("__nfs_fhget: killing %s/%s filehandle\n", + dentry->d_parent->d_name.name, + dentry->d_name.name); + memset(dentry->d_fsdata, 0, sizeof(struct nfs_fh)); - } else - printk("NFS: inode %ld busy, no aliases?\n", - inode->i_ino); - make_bad_inode(inode); + } remove_inode_hash(inode); + nfs_invalidate_inode(inode); + unhashed = 0; } iput(inode); goto retry; @@ -660,10 +706,6 @@ int status = 0; struct nfs_fattr fattr; - /* Don't bother revalidating if we've done it recently */ - if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode)) - goto out; - dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n", dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino); @@ -672,10 +714,9 @@ int error; u32 *fh; struct nfs_fh fhandle; -#ifdef NFS_PARANOIA -printk("nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status); -#endif + dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, inode->i_ino, status); if (status != -ESTALE) goto out; /* @@ -683,26 +724,25 @@ * and find out what the filehandle should be. */ fh = (u32 *) NFS_FH(dentry); - printk("NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n", + dfprintk(PAGECACHE, "NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n", fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]); error = nfs_proc_lookup(server, NFS_FH(dentry->d_parent), dentry->d_name.name, &fhandle, &fattr); if (error) { - printk("NFS: lookup failed, error=%d\n", error); + dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error); goto out; } fh = (u32 *) &fhandle; - printk(" %08x%08x%08x%08x%08x%08x%08x%08x\n", + dfprintk(PAGECACHE, " %08x%08x%08x%08x%08x%08x%08x%08x\n", fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]); goto out; } status = nfs_refresh_inode(inode, &fattr); if (status) { -#ifdef NFS_PARANOIA -printk("nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status); -#endif + dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, inode->i_ino, status); goto out; } dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n", @@ -808,29 +848,18 @@ printk("nfs_refresh_inode: inode %ld mode changed, %07o to %07o\n", inode->i_ino, inode->i_mode, fattr->mode); #endif - fattr->mode = inode->i_mode; /* save mode */ - make_bad_inode(inode); - nfs_inval(inode); - inode->i_mode = fattr->mode; /* restore mode */ /* * No need to worry about unhashing the dentry, as the * lookup validation will know that the inode is bad. - * (But we fall through to invalidate the caches.) */ + nfs_invalidate_inode(inode); + goto out; out_invalid: - /* - * Invalidate the local caches - */ #ifdef NFS_DEBUG_VERBOSE printk("nfs_refresh_inode: invalidating %ld pages\n", inode->i_nrpages); #endif - if (!S_ISDIR(inode->i_mode)) - invalidate_inode_pages(inode); - else - nfs_invalidate_dircache(inode); - NFS_CACHEINV(inode); - NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); + nfs_zap_caches(inode); goto out; } diff -u --recursive --new-file v2.2.6/linux/fs/nls/Config.in linux/fs/nls/Config.in --- v2.2.6/linux/fs/nls/Config.in Wed Jan 13 15:00:43 1999 +++ linux/fs/nls/Config.in Tue Apr 20 15:17:20 1999 @@ -4,7 +4,7 @@ # msdos and Joliet want NLS if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \ - -o "$CONFIG_NTFS_FS" != "n" ]; then + -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" ]; then define_bool CONFIG_NLS y else define_bool CONFIG_NLS n diff -u --recursive --new-file v2.2.6/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c --- v2.2.6/linux/fs/ntfs/fs.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ntfs/fs.c Fri Apr 23 21:20:38 1999 @@ -215,7 +215,6 @@ ntfs_debug(DEBUG_OTHER, "ntfs_readdir ino %x mode %x\n", (unsigned)dir->i_ino,(unsigned int)dir->i_mode); - if(!dir || (dir->i_ino==0) || !S_ISDIR(dir->i_mode))return -EBADF; ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n", (unsigned)filp->f_pos,dir->i_count); @@ -373,7 +372,7 @@ return 0; } -static int ntfs_lookup(struct inode *dir, struct dentry *d) +static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *d) { struct inode *res=0; char *item=0; @@ -385,10 +384,10 @@ error=ntfs_decodeuni(NTFS_INO2VOL(dir),(char*)d->d_name.name, d->d_name.len,&walk.name,&walk.namelen); if(error) - return error; + return ERR_PTR(-error); item=ntfs_malloc(ITEM_SIZE); if( !item ) - return ENOMEM; + return ERR_PTR(-ENOMEM); /* ntfs_getdir will place the directory entry into item, and the first long long is the MFT record number */ walk.type=BY_NAME; @@ -402,7 +401,7 @@ ntfs_free(item); ntfs_free(walk.name); /* Always return success, the dcache will handle negative entries. */ - return 0; + return NULL; } static struct file_operations ntfs_file_operations_nommap = { @@ -829,7 +828,7 @@ error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks ); if( error ) - return error; + return -error; fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap); fs.f_bavail=fs.f_bfree; diff -u --recursive --new-file v2.2.6/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c --- v2.2.6/linux/fs/ntfs/inode.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ntfs/inode.c Sat Apr 24 17:51:48 1999 @@ -150,6 +150,8 @@ ntfs_insert_fixups(buf,vol->blocksize); io.param=buf; io.size=vol->mft_recordsize; + io.fn_put = ntfs_put; + io.fn_get = ntfs_get; error=ntfs_write_attr(vol->mft_ino,vol->at_data,0, (rcount-1)*vol->mft_recordsize,&io); if(error)return error; diff -u --recursive --new-file v2.2.6/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.2.6/linux/fs/proc/fd.c Thu Nov 19 09:56:28 1998 +++ linux/fs/proc/fd.c Fri Apr 23 21:20:38 1999 @@ -19,7 +19,7 @@ #include static int proc_readfd(struct file *, void *, filldir_t); -static int proc_lookupfd(struct inode *, struct dentry *); +static struct dentry *proc_lookupfd(struct inode *, struct dentry *); static struct file_operations proc_fd_operations = { NULL, /* lseek - default */ @@ -67,7 +67,7 @@ * * Thus just return -ENOENT instead. */ -static int proc_lookupfd(struct inode * dir, struct dentry * dentry) +static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) { unsigned int ino, pid, fd, c; struct task_struct * p; @@ -77,13 +77,11 @@ int len, err; err = -ENOENT; - if (!dir) - goto out; ino = dir->i_ino; pid = ino >> 16; ino &= 0x0000ffff; - if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode)) + if (!pid || ino != PROC_PID_FD) goto out; fd = 0; @@ -121,10 +119,10 @@ if (inode) { dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); - err = 0; + return NULL; } out: - return err; + return ERR_PTR(err); } #define NUMBUF 10 @@ -136,10 +134,6 @@ unsigned int fd, pid, ino; int retval; char buf[NUMBUF]; - - retval = -EBADF; - if (!inode || !S_ISDIR(inode->i_mode)) - goto out; retval = 0; ino = inode->i_ino; diff -u --recursive --new-file v2.2.6/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.2.6/linux/fs/proc/openpromfs.c Thu Nov 19 09:56:29 1998 +++ linux/fs/proc/openpromfs.c Wed Apr 28 08:47:39 1999 @@ -1,4 +1,4 @@ -/* $Id: openpromfs.c,v 1.32 1998/11/18 06:15:20 davem Exp $ +/* $Id: openpromfs.c,v 1.33 1999/04/28 11:57:33 davem Exp $ * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -59,7 +59,7 @@ static int openpromfs_create (struct inode *, struct dentry *, int); static int openpromfs_readdir(struct file *, void *, filldir_t); -static int openpromfs_lookup(struct inode *, struct dentry *dentry); +static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry); static int openpromfs_unlink (struct inode *, struct dentry *dentry); static ssize_t nodenum_read(struct file *file, char *buf, @@ -685,7 +685,7 @@ return 0; } -static int openpromfs_lookup(struct inode * dir, struct dentry *dentry) +static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry) { int ino = 0; #define OPFSL_DIR 0 @@ -776,11 +776,11 @@ if (ino) type = OPFSL_DIR; else - return -ENOENT; + return ERR_PTR(-ENOENT); } inode = proc_get_inode (dir->i_sb, ino, 0); if (!inode) - return -EINVAL; + return ERR_PTR(-EINVAL); switch (type) { case OPFSL_DIR: inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; @@ -827,7 +827,7 @@ inode->i_uid = 0; d_add(dentry, inode); - return 0; + return NULL; } static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir) @@ -842,7 +842,6 @@ struct openpromfs_dev *d; char buffer2[64]; - if (!inode || !S_ISDIR (inode->i_mode)) return -ENOTDIR; ino = inode->i_ino; i = filp->f_pos; switch (i) { diff -u --recursive --new-file v2.2.6/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.2.6/linux/fs/proc/root.c Tue Jan 19 11:32:52 1999 +++ linux/fs/proc/root.c Wed Apr 28 08:47:39 1999 @@ -28,7 +28,7 @@ #define FIRST_PROCESS_ENTRY 256 static int proc_root_readdir(struct file *, void *, filldir_t); -static int proc_root_lookup(struct inode *,struct dentry *); +static struct dentry *proc_root_lookup(struct inode *,struct dentry *); static int proc_unlink(struct inode *, struct dentry *); static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0}; @@ -181,14 +181,14 @@ #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE) static int (*proc_openprom_defreaddir_ptr)(struct file *, void *, filldir_t); -static int (*proc_openprom_deflookup_ptr)(struct inode *, struct dentry *); +static struct dentry * (*proc_openprom_deflookup_ptr)(struct inode *, struct dentry *); void (*proc_openprom_use)(struct inode *, int) = 0; static struct openpromfs_dev *proc_openprom_devices = NULL; static ino_t proc_openpromdev_ino = PROC_OPENPROMD_FIRST; struct inode_operations * proc_openprom_register(int (*readdir)(struct file *, void *, filldir_t), - int (*lookup)(struct inode *, struct dentry *), + struct dentry * (*lookup)(struct inode *, struct dentry *), void (*use)(struct inode *, int), struct openpromfs_dev ***devices) { @@ -250,7 +250,7 @@ } #define OPENPROM_DEFREADDIR proc_openprom_defreaddir -static int +static struct dentry * proc_openprom_deflookup(struct inode * dir, struct dentry *dentry) { request_module("openpromfs"); @@ -258,7 +258,7 @@ proc_openprom_deflookup) return proc_openprom_inode_operations.lookup (dir, dentry); - return -ENOENT; + return ERR_PTR(-ENOENT); } #define OPENPROM_DEFLOOKUP proc_openprom_deflookup #else @@ -769,16 +769,12 @@ * Don't create negative dentries here, return -ENOENT by hand * instead. */ -int proc_lookup(struct inode * dir, struct dentry *dentry) +struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry) { struct inode *inode; struct proc_dir_entry * de; int error; - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) - goto out; - error = -ENOENT; inode = NULL; de = (struct proc_dir_entry *) dir->u.generic_ip; @@ -800,13 +796,12 @@ if (inode) { dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); - error = 0; + return NULL; } -out: - return error; + return ERR_PTR(error); } -static int proc_root_lookup(struct inode * dir, struct dentry * dentry) +static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry) { unsigned int pid, c; struct task_struct *p; @@ -826,7 +821,7 @@ } if (!proc_lookup(dir, dentry)) - return 0; + return NULL; pid = 0; name = dentry->d_name.name; @@ -853,13 +848,13 @@ unsigned long ino = (pid << 16) + PROC_PID_INO; inode = proc_get_inode(dir->i_sb, ino, &proc_pid); if (!inode) - return -EINVAL; + return ERR_PTR(-EINVAL); inode->i_flags|=S_IMMUTABLE; } dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); - return 0; + return NULL; } /* @@ -879,8 +874,6 @@ int i; struct inode *inode = filp->f_dentry->d_inode; - if (!inode || !S_ISDIR(inode->i_mode)) - return -ENOTDIR; ino = inode->i_ino; de = (struct proc_dir_entry *) inode->u.generic_ip; if (!de) diff -u --recursive --new-file v2.2.6/linux/fs/qnx4/dir.c linux/fs/qnx4/dir.c --- v2.2.6/linux/fs/qnx4/dir.c Sat Sep 5 16:46:41 1998 +++ linux/fs/qnx4/dir.c Fri Apr 23 21:20:38 1999 @@ -35,9 +35,6 @@ blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 + ((filp->f_pos >> 6) >> 3); - if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) { - return -EBADF; - } QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos)); QNX4DEBUG(("BlkNum = %ld\n", (long) blknum)); diff -u --recursive --new-file v2.2.6/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c --- v2.2.6/linux/fs/qnx4/namei.c Tue Dec 22 14:16:57 1998 +++ linux/fs/qnx4/namei.c Fri Apr 23 21:20:38 1999 @@ -108,7 +108,7 @@ return NULL; } -int qnx4_lookup(struct inode *dir, struct dentry *dentry) +struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry) { int ino; struct qnx4_inode_entry *de; @@ -116,17 +116,10 @@ struct buffer_head *bh; const char *name = dentry->d_name.name; int len = dentry->d_name.len; - struct inode *foundinode; + struct inode *foundinode = NULL; - if (!dir) { - return -EBADF; - } - if (!S_ISDIR(dir->i_mode)) { - return -EBADF; - } - if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino))) { - return -ENOENT; - } + if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino))) + goto out; /* The entry is linked, let's get the real info */ if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) { lnk = (struct qnx4_link_info *) de; @@ -137,11 +130,12 @@ if ((foundinode = iget(dir->i_sb, ino)) == NULL) { QNX4DEBUG(("qnx4: lookup->iget -> NULL\n")); - return -EACCES; + return ERR_PTR(-EACCES); } +out: d_add(dentry, foundinode); - return 0; + return NULL; } #ifdef CONFIG_QNX4FS_RW diff -u --recursive --new-file v2.2.6/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.2.6/linux/fs/romfs/inode.c Mon Sep 28 10:51:35 1998 +++ linux/fs/romfs/inode.c Fri Apr 23 21:20:38 1999 @@ -267,9 +267,6 @@ int stored = 0; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ - if (!i || !S_ISDIR(i->i_mode)) - return -EBADF; - maxoff = i->i_sb->u.romfs_sb.s_maxsize; offset = filp->f_pos; @@ -312,7 +309,7 @@ } } -static int +static struct dentry * romfs_lookup(struct inode *dir, struct dentry *dentry) { unsigned long offset, maxoff; @@ -323,10 +320,6 @@ const char *name; /* got from dentry */ int len; - res = -EBADF; - if (!dir || !S_ISDIR(dir->i_mode)) - goto out; - res = 0; /* instead of ENOENT */ offset = dir->i_ino & ROMFH_MASK; if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) @@ -379,7 +372,7 @@ } out: - return res; + return ERR_PTR(res); } /* diff -u --recursive --new-file v2.2.6/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c --- v2.2.6/linux/fs/smbfs/dir.c Fri Apr 16 14:47:31 1999 +++ linux/fs/smbfs/dir.c Fri Apr 23 21:20:38 1999 @@ -22,7 +22,7 @@ static int smb_readdir(struct file *, void *, filldir_t); static int smb_dir_open(struct inode *, struct file *); -static int smb_lookup(struct inode *, struct dentry *); +static struct dentry *smb_lookup(struct inode *, struct dentry *); static int smb_create(struct inode *, struct dentry *, int); static int smb_mkdir(struct inode *, struct dentry *, int); static int smb_rmdir(struct inode *, struct dentry *); @@ -324,7 +324,7 @@ } } -static int +static struct dentry * smb_lookup(struct inode *dir, struct dentry *dentry) { struct smb_fattr finfo; @@ -360,7 +360,7 @@ } } out: - return error; + return ERR_PTR(error); } /* diff -u --recursive --new-file v2.2.6/linux/fs/sysv/dir.c linux/fs/sysv/dir.c --- v2.2.6/linux/fs/sysv/dir.c Thu Nov 12 16:21:23 1998 +++ linux/fs/sysv/dir.c Fri Apr 23 21:20:38 1999 @@ -69,14 +69,12 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct super_block * sb; + struct super_block * sb = inode->i_sb; unsigned int offset,i; struct buffer_head * bh; char* bh_data; struct sysv_dir_entry * de, sde; - if (!inode || !(sb = inode->i_sb) || !S_ISDIR(inode->i_mode)) - return -EBADF; if ((unsigned long)(filp->f_pos) % SYSV_DIRSIZE) return -EBADF; while (filp->f_pos < inode->i_size) { diff -u --recursive --new-file v2.2.6/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v2.2.6/linux/fs/sysv/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/sysv/namei.c Fri Apr 23 21:20:38 1999 @@ -103,17 +103,12 @@ return NULL; } -int sysv_lookup(struct inode * dir, struct dentry * dentry) +struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry) { struct inode * inode = NULL; struct sysv_dir_entry * de; struct buffer_head * bh; - if (!dir) - return -ENOENT; - if (!S_ISDIR(dir->i_mode)) { - return -ENOENT; - } bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { @@ -122,10 +117,10 @@ inode = iget(dir->i_sb, ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); - return 0; + return NULL; } /* @@ -209,8 +204,6 @@ struct buffer_head * bh; struct sysv_dir_entry * de; - if (!dir) - return -ENOENT; inode = sysv_new_inode(dir); if (!inode) return -ENOSPC; @@ -239,8 +232,6 @@ struct buffer_head * bh; struct sysv_dir_entry * de; - if (!dir) - return -ENOENT; bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { @@ -286,8 +277,6 @@ struct buffer_head * bh, *dir_block; struct sysv_dir_entry * de; - if (!dir) - return -EINVAL; bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { diff -u --recursive --new-file v2.2.6/linux/fs/ufs/dir.c linux/fs/ufs/dir.c --- v2.2.6/linux/fs/ufs/dir.c Tue Jan 19 11:32:52 1999 +++ linux/fs/ufs/dir.c Fri Apr 23 21:20:38 1999 @@ -43,13 +43,6 @@ int de_reclen; unsigned flags, swab; - - /* Isn't that already done in the upper layer??? - * the VFS layer really needs some explicit documentation! - */ - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; - sb = inode->i_sb; swab = sb->u.ufs_sb.s_swab; flags = sb->u.ufs_sb.s_flags; diff -u --recursive --new-file v2.2.6/linux/fs/ufs/namei.c linux/fs/ufs/namei.c --- v2.2.6/linux/fs/ufs/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/ufs/namei.c Fri Apr 23 21:20:38 1999 @@ -185,7 +185,7 @@ return NULL; } -int ufs_lookup(struct inode * dir, struct dentry *dentry) +struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry) { struct super_block * sb; struct inode * inode; @@ -199,7 +199,7 @@ swab = sb->u.ufs_sb.s_swab; if (dentry->d_name.len > UFS_MAXNAMLEN) - return -ENAMETOOLONG; + return ERR_PTR(-ENAMETOOLONG); bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); inode = NULL; @@ -208,11 +208,11 @@ brelse (bh); inode = iget(sb, ino); if (!inode) - return -EACCES; + return ERR_PTR(-EACCES); } d_add(dentry, inode); UFSD(("EXIT\n")) - return 0; + return NULL; } /* diff -u --recursive --new-file v2.2.6/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c --- v2.2.6/linux/fs/umsdos/dir.c Fri Apr 16 14:47:31 1999 +++ linux/fs/umsdos/dir.c Fri Apr 23 21:20:38 1999 @@ -210,8 +210,8 @@ /* * Do a real lookup on the short name. */ - dret = umsdos_lookup_dentry(filp->f_dentry, info.fake.fname, - info.fake.len, 1); + dret = umsdos_covered(filp->f_dentry, info.fake.fname, + info.fake.len); ret = PTR_ERR(dret); if (IS_ERR(dret)) break; @@ -459,7 +459,7 @@ * entry from the EMD file, and return ENOENT. */ -int umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo) +struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo) { struct dentry *dret = NULL; struct inode *inode; @@ -500,8 +500,7 @@ info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len)); /* do a real lookup to get the short name ... */ - dret = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(dret); if (IS_ERR(dret)) { printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n", @@ -563,7 +562,7 @@ dput(dret); out: umsdos_endlookup (dir); - return ret; + return ERR_PTR(ret); out_remove: printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n", @@ -581,19 +580,19 @@ * Called by VFS; should fill dentry->d_inode via d_add. */ -int UMSDOS_lookup (struct inode *dir, struct dentry *dentry) +struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry) { - int ret; + struct dentry *ret; ret = umsdos_lookup_x (dir, dentry, 0); /* Create negative dentry if not found. */ - if (ret == -ENOENT) { + if (ret == ERR_PTR(-ENOENT)) { Printk ((KERN_DEBUG "UMSDOS_lookup: converting -ENOENT to negative\n")); d_add (dentry, NULL); dentry->d_op = &umsdos_dentry_operations; - ret = 0; + ret = NULL; } return ret; } @@ -601,7 +600,6 @@ struct dentry *umsdos_covered(struct dentry *parent, char *name, int len) { struct dentry *result, *dentry; - int error; struct qstr qstr; qstr.name = name; @@ -610,19 +608,18 @@ result = ERR_PTR(-ENOMEM); dentry = d_alloc(parent, &qstr); if (dentry) { - result = dentry; /* XXXXXXXXXXXXXXXXXXX Race alert! */ - error = UMSDOS_rlookup(parent->d_inode, result); - d_drop(result); - if (error) + result = UMSDOS_rlookup(parent->d_inode, dentry); + d_drop(dentry); + if (result) goto out_fail; + return dentry; } out: return result; out_fail: - dput(result); - result = ERR_PTR(error); + dput(dentry); goto out; } @@ -636,7 +633,6 @@ int real) { struct dentry *result, *dentry; - int error; struct qstr qstr; qstr.name = name; @@ -647,20 +643,19 @@ result = ERR_PTR(-ENOMEM); dentry = d_alloc(parent, &qstr); if (dentry) { - result = dentry; - error = real ? - UMSDOS_rlookup(parent->d_inode, result) : - UMSDOS_lookup(parent->d_inode, result); - if (error) + result = real ? + UMSDOS_rlookup(parent->d_inode, dentry) : + UMSDOS_lookup(parent->d_inode, dentry); + if (result) goto out_fail; + return dentry; } } out: return result; out_fail: - dput(result); - result = ERR_PTR(error); + dput(dentry); goto out; } diff -u --recursive --new-file v2.2.6/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c --- v2.2.6/linux/fs/umsdos/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/umsdos/namei.c Fri Apr 23 21:20:38 1999 @@ -175,18 +175,6 @@ #endif -/* - * Check whether we can delete from the directory. - */ -static int is_sticky(struct inode *dir, int uid) -{ - return !((dir->i_mode & S_ISVTX) == 0 || - current->fsuid == uid || - current->fsuid == dir->i_uid || - capable (CAP_FOWNER)); -} - - static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry, int errcod) { @@ -696,9 +684,8 @@ olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname)); /* Do a real lookup to get the short name dentry */ - temp = umsdos_lookup_dentry(olddentry->d_parent, - old_info.fake.fname, - old_info.fake.len, 1); + temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, + old_info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_unlock; @@ -784,16 +771,11 @@ goto out; /* lookup the short name dentry */ - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_remove; - /* Keep the short name dentry anonymous */ - if (temp != dentry) - d_drop(temp); - /* Make sure the short name doesn't exist */ ret = -EEXIST; if (temp->d_inode) { @@ -812,16 +794,9 @@ inode = temp->d_inode; down(&inode->i_sem); - /* - * Note! The long and short name might be the same, - * so check first before doing the instantiate ... - */ - if (dentry != temp) { -if (dentry->d_inode) -printk("umsdos_mkdir: dentry not negative!\n"); - inode->i_count++; - d_instantiate(dentry, inode); - } + inode->i_count++; + d_instantiate(dentry, inode); + /* N.B. this should have an option to create the EMD ... */ umsdos_lookup_patch_new(dentry, &info); @@ -921,21 +896,11 @@ umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); /* Call findentry to complete the mangling */ umsdos_findentry (dentry->d_parent, &info, 2); - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out; /* - * If the short name is an alias, dput() it now; - * otherwise d_drop() it to keep it anonymous. - */ - if (temp == dentry) - dput(temp); - else - d_drop(temp); - - /* * Attempt to remove the msdos name. */ ret = msdos_rmdir (dir, temp); @@ -951,8 +916,7 @@ /* dput() temp if we didn't do it above */ out_dput: - if (temp != dentry) - dput(temp); + dput(temp); out: Printk (("umsdos_rmdir %d\n", ret)); @@ -999,14 +963,6 @@ Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname)); - ret = -EPERM; - /* check sticky bit */ - if (is_sticky(dir, info.entry.uid)) { -printk("umsdos_unlink: %s/%s is sticky\n", -dentry->d_parent->d_name.name, dentry->d_name.name); - goto out_unlock; - } - /* * Note! If this is a hardlink and the names are aliased, * the short-name lookup will return the hardlink dentry. @@ -1018,8 +974,7 @@ } /* Do a real lookup to get the short name dentry */ - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_unlock; @@ -1031,13 +986,6 @@ link = umsdos_solve_hlink(dget(temp)); } - /* - * If the short and long names are aliased, - * dput() it now so the dentry isn't busy. - */ - if (temp == dentry) - dput(temp); - /* Delete the EMD entry */ ret = umsdos_delentry (dentry->d_parent, &info, 0); if (ret && ret != -ENOENT) { @@ -1046,7 +994,7 @@ goto out_dput; } - ret = msdos_unlink_umsdos (dir, temp); + ret = msdos_unlink(dir, temp); #ifdef UMSDOS_PARANOIA if (ret) printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n", @@ -1055,12 +1003,9 @@ /* dput() temp if we didn't do it above */ out_dput: - if (temp != dentry) { - d_drop(temp); - dput(temp); - if (!ret) - d_delete (dentry); - } + dput(temp); + if (!ret) + d_delete (dentry); out_unlock: umsdos_unlockcreate (dir); diff -u --recursive --new-file v2.2.6/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c --- v2.2.6/linux/fs/umsdos/rdir.c Wed Dec 16 10:32:56 1998 +++ linux/fs/umsdos/rdir.c Fri Apr 23 21:20:38 1999 @@ -79,9 +79,9 @@ * In the real root directory (c:\), the directory .. * is the pseudo root (c:\linux). */ -int umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) +struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) { - int ret; + struct dentry *ret; if (saved_root && dir == saved_root->d_inode && !nopseudo && dentry->d_name.len == UMSDOS_PSDROOT_LEN && @@ -91,15 +91,16 @@ * /linux won't show */ - ret = -ENOENT; + ret = ERR_PTR(-ENOENT); goto out; } ret = msdos_lookup (dir, dentry); if (ret) { printk(KERN_WARNING - "umsdos_rlookup_x: %s/%s failed, ret=%d\n", - dentry->d_parent->d_name.name, dentry->d_name.name,ret); + "umsdos_rlookup_x: %s/%s failed, ret=%ld\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + PTR_ERR(ret)); goto out; } if (dentry->d_inode) { @@ -119,7 +120,7 @@ } -int UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry) +struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry) { return umsdos_rlookup_x (dir, dentry, 0); } diff -u --recursive --new-file v2.2.6/linux/fs/vfat/namei.c linux/fs/vfat/namei.c --- v2.2.6/linux/fs/vfat/namei.c Fri Apr 16 14:47:31 1999 +++ linux/fs/vfat/namei.c Fri Apr 23 21:20:38 1999 @@ -1140,11 +1140,30 @@ return res; } -int vfat_lookup(struct inode *dir,struct dentry *dentry) +/* Find a hashed dentry for inode; NULL if there are none */ +static struct dentry *find_alias(struct inode *inode) +{ + struct list_head *head, *next, *tmp; + struct dentry *alias; + + head = &inode->i_dentry; + next = inode->i_dentry.next; + while (next != head) { + tmp = next; + next = tmp->next; + alias = list_entry(tmp, struct dentry, d_alias); + if (!list_empty(&alias->d_hash)) + return dget(alias); + } + return NULL; +} + +struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry) { int res; struct vfat_slot_info sinfo; struct inode *result; + struct dentry *alias; int table; PRINTK2(("vfat_lookup: name=%s, len=%d\n", @@ -1161,7 +1180,7 @@ } PRINTK3(("vfat_lookup 4.5\n")); if (!(result = iget(dir->i_sb,sinfo.ino))) - return -EACCES; + return ERR_PTR(-EACCES); PRINTK3(("vfat_lookup 5\n")); if (MSDOS_I(result)->i_busy) { /* mkdir in progress */ iput(result); @@ -1169,6 +1188,15 @@ table++; goto error; } + alias = find_alias(result); + if (alias) { + if (d_invalidate(alias)==0) + dput(alias); + else { + iput(result); + return alias; + } + } PRINTK3(("vfat_lookup 6\n")); error: dentry->d_op = &vfat_dentry_ops[table]; @@ -1397,28 +1425,6 @@ return 0; } -/* Drop all aliases */ -static void drop_aliases(struct dentry *dentry) -{ - struct list_head *head, *next, *tmp; - struct dentry *alias; - - PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry, inode)); - head = &dentry->d_inode->i_dentry; - if (dentry->d_inode) { - next = dentry->d_inode->i_dentry.next; - while (next != head) { - tmp = next; - next = tmp->next; - alias = list_entry(tmp, struct dentry, d_alias); - if (alias == dentry) - continue; - - d_drop(alias); - } - } -} - static int vfat_rmdirx(struct inode *dir,struct dentry* dentry) { int res; @@ -1430,12 +1436,6 @@ if (res >= 0 && sinfo.total_slots > 0) { if (!list_empty(&dentry->d_hash)) return -EBUSY; - /* Take care of aliases */ - if (dentry->d_inode->i_count > 1) { - shrink_dcache_parent(dentry->d_parent); - if (dentry->d_inode->i_count > 1) - return -EBUSY; - } res = vfat_empty(dentry->d_inode); if (res) return res; @@ -1535,10 +1535,8 @@ PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode)); res = vfat_unlinkx (dir,dentry,1); - if (res >= 0) { - drop_aliases(dentry); + if (res >= 0) d_delete(dentry); - } return res; } @@ -1561,7 +1559,6 @@ loff_t old_offset,new_offset,old_longname_offset; int old_slots,old_ino,new_ino,dotdot_ino; struct inode *old_inode, *new_inode, *dotdot_inode; - struct dentry *walk; int res, is_dir, i; int locked = 0; struct vfat_slot_info sinfo; @@ -1589,16 +1586,6 @@ old_inode = old_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); - if (is_dir) { - /* We can't use is_subdir() here. Even now. Arrgh. */ - for (walk=new_dentry;walk!=walk->d_parent;walk=walk->d_parent) { - if (walk->d_inode != old_dentry->d_inode) - continue; - res = -EINVAL; - goto rename_done; - } - } - fat_lock_creation(); locked = 1; if (new_dentry->d_inode) { @@ -1620,25 +1607,9 @@ } if (is_dir) { - /* - * Target is a directory. No other owners will - * be tolerated. - */ - res = -EBUSY; - /* - * OK, let's try to get rid of other dentries. - * No need to do it if i_count is 1. - */ - if (new_inode->i_count>1) { - shrink_dcache_parent(new_dentry->d_parent); - if (new_inode->i_count>1) - goto rename_done; - } res = vfat_empty(new_inode); if (res) goto rename_done; - } else { - drop_aliases(new_dentry); } res = vfat_remove_entry(new_dir,&sinfo,new_inode); if (res) diff -u --recursive --new-file v2.2.6/linux/include/asm-alpha/keyboard.h linux/include/asm-alpha/keyboard.h --- v2.2.6/linux/include/asm-alpha/keyboard.h Thu Jul 31 13:09:18 1997 +++ linux/include/asm-alpha/keyboard.h Mon Apr 26 10:54:25 1999 @@ -18,7 +18,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -28,7 +27,6 @@ #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate #define kbd_translate pckbd_translate #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds diff -u --recursive --new-file v2.2.6/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h --- v2.2.6/linux/include/asm-alpha/semaphore.h Fri Apr 16 14:47:31 1999 +++ linux/include/asm-alpha/semaphore.h Sat Apr 24 17:54:08 1999 @@ -53,24 +53,31 @@ it's return address in $28. The pv is loaded as usual. The gp is clobbered (in the module case) as usual. */ + /* This little bit of silliness is to get the GP loaded for + a function that ordinarily wouldn't. Otherwise we could + have it done by the macro directly, which can be optimized + the linker. */ + register void *pv __asm__("$27") = __down_failed; + __asm__ __volatile__ ( "/* semaphore down operation */\n" - "1: ldl_l $27,%0\n" - " subl $27,1,$27\n" - " mov $27,$28\n" - " stl_c $28,%0\n" + "1: ldl_l $24,%1\n" + " subl $24,1,$24\n" + " mov $24,$28\n" + " stl_c $28,%1\n" " beq $28,2f\n" - " blt $27,3f\n" + " blt $24,3f\n" "4: mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" - "3: lda $24,%0\n" - " jsr $28,__down_failed\n" + "3: lda $24,%1\n" + " jsr $28,($27),__down_failed\n" " ldgp $29,0($28)\n" " br 4b\n" ".previous" - : : "m"(sem->count) - : "$24", "$27", "$28", "memory"); + : "=r"(pv) + : "m"(sem->count), "r"(pv) + : "$24", "$28", "memory"); } extern inline int down_interruptible(struct semaphore * sem) @@ -81,27 +88,28 @@ value is in $24. */ register int ret __asm__("$24"); + register void *pv __asm__("$27") = __down_failed_interruptible; __asm__ __volatile__ ( "/* semaphore down interruptible operation */\n" - "1: ldl_l $27,%1\n" - " subl $27,1,$27\n" - " mov $27,$28\n" - " stl_c $28,%1\n" + "1: ldl_l $24,%2\n" + " subl $24,1,$24\n" + " mov $24,$28\n" + " stl_c $28,%2\n" " beq $28,2f\n" - " blt $27,3f\n" + " blt $24,3f\n" " mov $31,%0\n" "4: mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" - "3: lda $24,%1\n" - " jsr $28,__down_failed_interruptible\n" + "3: lda $24,%2\n" + " jsr $28,($27),__down_failed_interruptible\n" " ldgp $29,0($28)\n" " br 4b\n" ".previous" - : "=r"(ret) - : "m"(sem->count) - : "$27", "$28", "memory"); + : "=r"(ret), "=r"(pv) + : "m"(sem->count), "r"(pv) + : "$28", "memory"); return ret; } @@ -171,26 +179,29 @@ it's return address in $28. The pv is loaded as usual. The gp is clobbered (in the module case) as usual. */ + register void *pv __asm__("$27") = __up_wakeup; + __asm__ __volatile__ ( "/* semaphore up operation */\n" " mb\n" - "1: ldl_l $27,%0\n" - " addl $27,1,$27\n" - " mov $27,$28\n" - " stl_c $28,%0\n" + "1: ldl_l $24,%1\n" + " addl $24,1,$24\n" + " mov $24,$28\n" + " stl_c $28,%1\n" " beq $28,2f\n" " mb\n" " ble $27,3f\n" "4:\n" ".section .text2,\"ax\"\n" "2: br 1b\n" - "3: lda $24,%0\n" - " jsr $28,__up_wakeup\n" + "3: lda $24,%1\n" + " jsr $28,($27),__up_wakeup\n" " ldgp $29,0($28)\n" " br 4b\n" ".previous" - : : "m"(sem->count) - : "$24", "$27", "$28", "memory"); + : "=r"(pv) + : "m"(sem->count), "r"(pv) + : "$24", "$28", "memory"); } #endif diff -u --recursive --new-file v2.2.6/linux/include/asm-alpha/siginfo.h linux/include/asm-alpha/siginfo.h --- v2.2.6/linux/include/asm-alpha/siginfo.h Thu Aug 20 17:05:18 1998 +++ linux/include/asm-alpha/siginfo.h Mon Apr 26 15:55:54 1999 @@ -138,7 +138,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h --- v2.2.6/linux/include/asm-alpha/uaccess.h Fri Apr 16 14:47:31 1999 +++ linux/include/asm-alpha/uaccess.h Sat Apr 24 17:54:08 1999 @@ -160,7 +160,7 @@ : "=r"(__gu_val), "=r"(__gu_err) \ : "m"(__m(addr)), "1"(__gu_err)) -#ifdef __HAVE_CPU_BWX +#ifdef __alpha_bwx__ /* Those lucky bastards with ev56 and later CPUs can do byte/word moves. */ #define __get_user_16(addr) \ @@ -274,7 +274,7 @@ : "=r"(__pu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(__pu_err)) -#ifdef __HAVE_CPU_BWX +#ifdef __alpha_bwx__ /* Those lucky bastards with ev56 and later CPUs can do byte/word moves. */ #define __put_user_16(x,addr) \ @@ -363,15 +363,21 @@ extern inline long __copy_tofrom_user_nocheck(void *to, const void *from, long len) { + /* This little bit of silliness is to get the GP loaded for + a function that ordinarily wouldn't. Otherwise we could + have it done by the macro directly, which can be optimized + the linker. */ + register void * pv __asm__("$27") = __copy_user; + register void * __cu_to __asm__("$6") = to; register const void * __cu_from __asm__("$7") = from; register long __cu_len __asm__("$0") = len; __asm__ __volatile__( - "jsr $28,__copy_user" - : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) - : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to) - : "$1","$2","$3","$4","$5","$27","$28","memory"); + "jsr $28,(%3),__copy_user\n\tldgp $29,0($28)" + : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to), "=r"(pv) + : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to), "3"(pv) + : "$1","$2","$3","$4","$5","$28","memory"); return __cu_len; } @@ -380,14 +386,17 @@ __copy_tofrom_user(void *to, const void *from, long len, const void *validate) { if (__access_ok((long)validate, len, get_fs())) { + register void * pv __asm__("$27") = __copy_user; register void * __cu_to __asm__("$6") = to; register const void * __cu_from __asm__("$7") = from; register long __cu_len __asm__("$0") = len; __asm__ __volatile__( - "jsr $28,__copy_user" - : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) - : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to) - : "$1","$2","$3","$4","$5","$27","$28","memory"); + "jsr $28,(%3),__copy_user\n\tldgp $29,0($28)" + : "=r"(__cu_len), "=r"(__cu_from), "=r"(__cu_to), + "=r" (pv) + : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to), + "3" (pv) + : "$1","$2","$3","$4","$5","$28","memory"); len = __cu_len; } return len; @@ -423,13 +432,19 @@ extern inline long __clear_user(void *to, long len) { + /* This little bit of silliness is to get the GP loaded for + a function that ordinarily wouldn't. Otherwise we could + have it done by the macro directly, which can be optimized + the linker. */ + register void * pv __asm__("$27") = __do_clear_user; + register void * __cl_to __asm__("$6") = to; register long __cl_len __asm__("$0") = len; __asm__ __volatile__( - "jsr $28,__do_clear_user" - : "=r"(__cl_len), "=r"(__cl_to) - : "0"(__cl_len), "1"(__cl_to) - : "$1","$2","$3","$4","$5","$27","$28","memory"); + "jsr $28,(%2),__do_clear_user\n\tldgp $29,0($28)" + : "=r"(__cl_len), "=r"(__cl_to), "=r"(pv) + : "0"(__cl_len), "1"(__cl_to), "2"(pv) + : "$1","$2","$3","$4","$5","$28","memory"); return __cl_len; } @@ -437,13 +452,14 @@ clear_user(void *to, long len) { if (__access_ok((long)to, len, get_fs())) { + register void * pv __asm__("$27") = __do_clear_user; register void * __cl_to __asm__("$6") = to; register long __cl_len __asm__("$0") = len; __asm__ __volatile__( - "jsr $28,__do_clear_user" - : "=r"(__cl_len), "=r"(__cl_to) - : "0"(__cl_len), "1"(__cl_to) - : "$1","$2","$3","$4","$5","$27","$28","memory"); + "jsr $28,(%2),__do_clear_user\n\tldgp $29,0($28)" + : "=r"(__cl_len), "=r"(__cl_to), "=r"(pv) + : "0"(__cl_len), "1"(__cl_to), "2"(pv) + : "$1","$2","$3","$4","$5","$28","memory"); len = __cl_len; } return len; diff -u --recursive --new-file v2.2.6/linux/include/asm-arm/arch-arc/keyboard.h linux/include/asm-arm/arch-arc/keyboard.h --- v2.2.6/linux/include/asm-arm/arch-arc/keyboard.h Tue Dec 22 14:16:57 1998 +++ linux/include/asm-arm/arch-arc/keyboard.h Mon Apr 26 10:56:18 1999 @@ -19,11 +19,6 @@ #define kbd_setkeycode(sc,kc) (-EINVAL) #define kbd_getkeycode(sc) (-EINVAL) -/* Prototype: int kbd_pretranslate(scancode, raw_mode) - * Returns : 0 to ignore scancode - */ -#define kbd_pretranslate(sc,rm) (1) - /* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode) * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag * set to 0200 if scancode indicates release diff -u --recursive --new-file v2.2.6/linux/include/asm-arm/arch-ebsa285/keyboard.h linux/include/asm-arm/arch-ebsa285/keyboard.h --- v2.2.6/linux/include/asm-arm/arch-ebsa285/keyboard.h Tue Dec 22 14:16:58 1998 +++ linux/include/asm-arm/arch-ebsa285/keyboard.h Mon Apr 26 10:56:18 1999 @@ -19,7 +19,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -29,7 +28,6 @@ #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate #define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \ pckbd_translate(sc & 0x7f, kcp, rm);}) @@ -49,11 +47,6 @@ #define kbd_setkeycode(sc,kc) (-EINVAL) #define kbd_getkeycode(sc) (-EINVAL) - -/* Prototype: int kbd_pretranslate(scancode, raw_mode) - * Returns : 0 to ignore scancode - */ -#define kbd_pretranslate(sc,rm) (1) /* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode) * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag diff -u --recursive --new-file v2.2.6/linux/include/asm-arm/arch-rpc/keyboard.h linux/include/asm-arm/arch-rpc/keyboard.h --- v2.2.6/linux/include/asm-arm/arch-rpc/keyboard.h Tue Dec 22 14:16:58 1998 +++ linux/include/asm-arm/arch-rpc/keyboard.h Mon Apr 26 10:55:47 1999 @@ -10,7 +10,6 @@ #define NR_SCANCODES 128 -extern int ps2kbd_pretranslate(unsigned char scancode); extern int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *up_flag_p); extern void ps2kbd_leds(unsigned char leds); extern void ps2kbd_init_hw(void); @@ -18,11 +17,6 @@ #define kbd_setkeycode(sc,kc) (-EINVAL) #define kbd_getkeycode(sc) (-EINVAL) - -/* Prototype: int kbd_pretranslate(scancode, raw_mode) - * Returns : 0 to ignore scancode - */ -#define kbd_pretranslate(sc,rm) ps2kbd_pretranslate(sc) /* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode) * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag diff -u --recursive --new-file v2.2.6/linux/include/asm-arm/arch-vnc/keyboard.h linux/include/asm-arm/arch-vnc/keyboard.h --- v2.2.6/linux/include/asm-arm/arch-vnc/keyboard.h Tue Dec 22 14:16:58 1998 +++ linux/include/asm-arm/arch-vnc/keyboard.h Mon Apr 26 10:56:18 1999 @@ -14,7 +14,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -24,7 +23,6 @@ #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate #define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \ pckbd_translate(sc & 0x7f, kcp, rm);}) diff -u --recursive --new-file v2.2.6/linux/include/asm-arm/siginfo.h linux/include/asm-arm/siginfo.h --- v2.2.6/linux/include/asm-arm/siginfo.h Thu Aug 20 17:05:18 1998 +++ linux/include/asm-arm/siginfo.h Mon Apr 26 15:55:54 1999 @@ -138,7 +138,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h --- v2.2.6/linux/include/asm-i386/bitops.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-i386/bitops.h Tue Apr 27 09:56:21 1999 @@ -46,7 +46,7 @@ __asm__ __volatile__( LOCK_PREFIX "btsl %1,%0" :"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); } extern __inline__ void clear_bit(int nr, volatile void * addr) @@ -54,7 +54,7 @@ __asm__ __volatile__( LOCK_PREFIX "btrl %1,%0" :"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); } extern __inline__ void change_bit(int nr, volatile void * addr) @@ -62,7 +62,7 @@ __asm__ __volatile__( LOCK_PREFIX "btcl %1,%0" :"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); } extern __inline__ int test_and_set_bit(int nr, volatile void * addr) @@ -72,7 +72,7 @@ __asm__ __volatile__( LOCK_PREFIX "btsl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); return oldbit; } @@ -83,7 +83,7 @@ __asm__ __volatile__( LOCK_PREFIX "btrl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); return oldbit; } @@ -94,7 +94,7 @@ __asm__ __volatile__( LOCK_PREFIX "btcl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); + :"Ir" (nr)); return oldbit; } @@ -113,7 +113,7 @@ __asm__ __volatile__( "btl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit) - :"m" (ADDR),"ir" (nr)); + :"m" (ADDR),"Ir" (nr)); return oldbit; } diff -u --recursive --new-file v2.2.6/linux/include/asm-i386/keyboard.h linux/include/asm-i386/keyboard.h --- v2.2.6/linux/include/asm-i386/keyboard.h Thu Jul 31 13:09:18 1997 +++ linux/include/asm-i386/keyboard.h Mon Apr 26 10:54:03 1999 @@ -18,7 +18,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -28,7 +27,6 @@ #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate #define kbd_translate pckbd_translate #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds diff -u --recursive --new-file v2.2.6/linux/include/asm-i386/siginfo.h linux/include/asm-i386/siginfo.h --- v2.2.6/linux/include/asm-i386/siginfo.h Thu Aug 20 17:05:18 1998 +++ linux/include/asm-i386/siginfo.h Mon Apr 26 15:55:54 1999 @@ -138,7 +138,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-i386/string.h linux/include/asm-i386/string.h --- v2.2.6/linux/include/asm-i386/string.h Wed Jan 20 23:14:06 1999 +++ linux/include/asm-i386/string.h Thu Apr 22 09:59:46 1999 @@ -462,7 +462,7 @@ #define __HAVE_ARCH_MEMSET #define memset(s, c, count) \ (__builtin_constant_p(c) ? \ - __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \ + __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \ __memset((s),(c),(count))) /* diff -u --recursive --new-file v2.2.6/linux/include/asm-m68k/keyboard.h linux/include/asm-m68k/keyboard.h --- v2.2.6/linux/include/asm-m68k/keyboard.h Wed Jan 20 23:14:06 1999 +++ linux/include/asm-m68k/keyboard.h Mon Apr 26 10:53:51 1999 @@ -27,11 +27,6 @@ return scancode > 127 ? -EINVAL : scancode; } -static __inline__ int kbd_pretranslate(unsigned char scancode, char raw_mode) -{ - return 1; -} - static __inline__ int kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { diff -u --recursive --new-file v2.2.6/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.2.6/linux/include/asm-mips/keyboard.h Fri Oct 23 22:01:22 1998 +++ linux/include/asm-mips/keyboard.h Mon Apr 26 10:54:13 1999 @@ -19,7 +19,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -29,7 +28,6 @@ #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate #define kbd_translate pckbd_translate #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds diff -u --recursive --new-file v2.2.6/linux/include/asm-mips/siginfo.h linux/include/asm-mips/siginfo.h --- v2.2.6/linux/include/asm-mips/siginfo.h Fri Oct 23 22:01:23 1998 +++ linux/include/asm-mips/siginfo.h Mon Apr 26 15:55:54 1999 @@ -146,7 +146,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h --- v2.2.6/linux/include/asm-ppc/keyboard.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-ppc/keyboard.h Mon Apr 26 10:55:17 1999 @@ -28,7 +28,6 @@ extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_pretranslate(unsigned char scancode, char raw_mode); extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern int mackbd_unexpected_up(unsigned char keycode); @@ -37,7 +36,6 @@ extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -82,23 +80,6 @@ #endif else return mackbd_getkeycode(x); -} - -static inline int kbd_pretranslate(unsigned char x,char y) -{ - if ( is_prep || (_machine == _MACH_mbx) ) - return pckbd_pretranslate(x,y); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_pretranslate(x,y); -#else - if ( adb_hardware == ADB_NONE ) - return pckbd_pretranslate(x,y); - else - return mackbd_pretranslate(x,y); -#endif - else - return mackbd_pretranslate(x,y); } static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep, diff -u --recursive --new-file v2.2.6/linux/include/asm-ppc/siginfo.h linux/include/asm-ppc/siginfo.h --- v2.2.6/linux/include/asm-ppc/siginfo.h Thu Aug 20 17:05:18 1998 +++ linux/include/asm-ppc/siginfo.h Mon Apr 26 15:55:54 1999 @@ -138,7 +138,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/asmmacro.h linux/include/asm-sparc/asmmacro.h --- v2.2.6/linux/include/asm-sparc/asmmacro.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/asmmacro.h Wed Apr 28 08:47:39 1999 @@ -26,7 +26,7 @@ #define GET_PROCESSOR_MID(reg, tmp) \ rd %tbr, %reg; \ - sethi C_LABEL(mid_xlate), %tmp; \ + sethi %hi(C_LABEL(mid_xlate)), %tmp; \ srl %reg, 12, %reg; \ or %tmp, %lo(C_LABEL(mid_xlate)), %tmp; \ and %reg, 3, %reg; \ @@ -34,7 +34,7 @@ #define GET_PROCESSOR_OFFSET(reg, tmp) \ GET_PROCESSOR_ID(reg) \ - sethi C_LABEL(cpu_offset), %tmp; \ + sethi %hi(C_LABEL(cpu_offset)), %tmp; \ sll %reg, 2, %reg; \ or %tmp, %lo(C_LABEL(cpu_offset)), %tmp; \ ld [%tmp + %reg], %reg; diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/atomic.h linux/include/asm-sparc/atomic.h --- v2.2.6/linux/include/asm-sparc/atomic.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc/atomic.h Thu Apr 22 19:24:51 1999 @@ -41,13 +41,14 @@ static __inline__ int atomic_read(atomic_t *v) { - int val; + int ret = v->counter; - __asm__ __volatile__("sra %1, 0x8, %0" - : "=r" (val) - : "r" (v->counter)); - return val; + while(ret & 0xff) + ret = v->counter; + + return ret >> 8; } + #define atomic_set(v, i) (((v)->counter) = ((i) << 8)) #endif diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/floppy.h linux/include/asm-sparc/floppy.h --- v2.2.6/linux/include/asm-sparc/floppy.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc/floppy.h Thu Apr 22 19:24:51 1999 @@ -15,6 +15,14 @@ #include #include +/* We don't need no stinkin' I/O port allocation crap. */ +#undef release_region +#undef check_region +#undef request_region +#define release_region(X, Y) do { } while(0) +#define check_region(X, Y) (0) +#define request_region(X, Y, Z) do { } while(0) + /* References: * 1) Netbsd Sun floppy driver. * 2) NCR 82077 controller manual @@ -320,8 +328,7 @@ "floppy", fd_regs[0].which_io, 0x0); - release_region((long)sun_fdc & PAGE_MASK, - (((long)sun_fdc & ~PAGE_MASK) + fd_regs[0].reg_size + PAGE_SIZE - 1) & PAGE_MASK); + /* Last minute sanity check... */ if(sun_fdc->status_82072 == 0xff) { sun_fdc = NULL; diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h --- v2.2.6/linux/include/asm-sparc/hardirq.h Sun Nov 8 14:03:09 1998 +++ linux/include/asm-sparc/hardirq.h Thu Apr 22 19:24:51 1999 @@ -1,7 +1,7 @@ /* hardirq.h: 32-bit Sparc hard IRQ support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) */ #ifndef __SPARC_HARDIRQ_H @@ -9,22 +9,20 @@ #include -extern unsigned int local_irq_count[NR_CPUS]; +#ifndef __SMP__ +extern unsigned int local_irq_count; /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ -#define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); }) +#define in_interrupt() ((local_irq_count + local_bh_count) != 0) -#ifndef __SMP__ - -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count == 0) #define hardirq_endlock(cpu) do { } while (0) -#define hardirq_enter(cpu) (local_irq_count[cpu]++) -#define hardirq_exit(cpu) (local_irq_count[cpu]--) +#define hardirq_enter(cpu) (local_irq_count++) +#define hardirq_exit(cpu) (local_irq_count--) #define synchronize_irq() barrier() @@ -35,10 +33,18 @@ #include #include +extern unsigned int local_irq_count[NR_CPUS]; extern unsigned char global_irq_holder; extern spinlock_t global_irq_lock; extern atomic_t global_irq_count; +/* + * Are we in an interrupt context? Either doing bottom half + * or hardware interrupt processing? + */ +#define in_interrupt() ({ int __cpu = smp_processor_id(); \ + (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); }) + static inline void release_irqlock(int cpu) { /* if we didn't own the irq lock, just ignore.. */ @@ -62,7 +68,8 @@ static inline int hardirq_trylock(int cpu) { - return !atomic_read(&global_irq_count) && !*(((volatile unsigned char *)(&global_irq_lock))); + return (! atomic_read(&global_irq_count) && + ! spin_is_locked (&global_irq_lock)); } #define hardirq_endlock(cpu) do { } while (0) diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h --- v2.2.6/linux/include/asm-sparc/head.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/head.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: head.h,v 1.35 1998/03/18 09:15:40 jj Exp $ */ +/* $Id: head.h,v 1.36 1999/04/20 13:22:42 anton Exp $ */ #ifndef __SPARC_HEAD_H #define __SPARC_HEAD_H @@ -7,8 +7,6 @@ #define SUN4C_SEGSZ (1 << 18) #define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2) /* Used in boot remapping. */ #define INTS_ENAB 0x01 /* entry.S uses this. */ - -#define NCPUS 4 /* Architectural limit of sun4m. */ #define SUN4_PROM_VECTOR 0xFFE81000 /* SUN4 PROM needs to be hardwired */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h --- v2.2.6/linux/include/asm-sparc/irq.h Thu Aug 6 14:06:34 1998 +++ linux/include/asm-sparc/irq.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.h,v 1.25 1998/06/04 09:55:04 jj Exp $ +/* $Id: irq.h,v 1.26 1999/04/20 13:22:44 anton Exp $ * irq.h: IRQ registers on the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -8,8 +8,9 @@ #define _SPARC_IRQ_H #include +#include /* For NR_CPUS */ -#include /* For NCPUS */ +#include /* For SUN4M_NCPUS */ #include #define __irq_ino(irq) irq @@ -19,46 +20,18 @@ #define NR_IRQS 15 -/* Get rid of this when lockups have gone away. -DaveM */ -#ifndef DEBUG_IRQLOCK -#define DEBUG_IRQLOCK -#endif - /* IRQ handler dispatch entry and exit. */ #ifdef __SMP__ -#ifdef DEBUG_IRQLOCK -extern void irq_enter(int cpu, int irq, void *regs); -extern void irq_exit(int cpu, int irq); -#else -extern __inline__ void irq_enter(int cpu, int irq, void *regs) -{ - register int proc asm("g1"); - proc = cpu; - __asm__ __volatile__(" - mov %%o7, %%g4 - call ___irq_enter - add %%o7, 8, %%o7 -" : "=&r" (proc) - : "0" (proc) - : "g2", "g3", "g4", "g5", "memory", "cc"); -} - -extern __inline__ void irq_exit(int cpu, int irq) -{ - register int proc asm("g7"); - proc = cpu; - __asm__ __volatile__(" - mov %%o7, %%g4 - call ___irq_exit - add %%o7, 8, %%o7 -" : "=&r" (proc) - : "0" (proc) - : "g1", "g2", "g3", "g4", "g5", "memory", "cc"); -} -#endif /* DEBUG_IRQLOCK */ +extern unsigned int local_irq_count[NR_CPUS]; +#define irq_enter(cpu, irq) \ +do { hardirq_enter(cpu); \ + spin_unlock_wait(&global_irq_lock); \ + } while(0) +#define irq_exit(cpu, irq) hardirq_exit(cpu) #else -#define irq_enter(cpu, irq, regs) (local_irq_count[cpu]++) -#define irq_exit(cpu, irq) (local_irq_count[cpu]--) +extern unsigned int local_irq_count; +#define irq_enter(cpu, irq) (local_irq_count++) +#define irq_exit(cpu, irq) (local_irq_count--) #endif /* Dave Redman (djhr@tadpole.co.uk) @@ -133,7 +106,7 @@ * sun4m machines, for MP the layout makes more sense. */ struct sun4m_intregs { - struct sun4m_intreg_percpu cpu_intregs[NCPUS]; + struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; unsigned int tbt; /* IRQ's that are still pending. */ unsigned int irqs; /* Master IRQ bits. */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/keyboard.h linux/include/asm-sparc/keyboard.h --- v2.2.6/linux/include/asm-sparc/keyboard.h Mon Oct 5 13:13:43 1998 +++ linux/include/asm-sparc/keyboard.h Wed Apr 28 08:47:39 1999 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.1 1998/09/22 05:54:42 jj Exp $ +/* $Id: keyboard.h,v 1.2 1999/04/28 11:59:07 davem Exp $ * linux/include/asm-sparc/keyboard.h * * sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) @@ -18,7 +18,6 @@ extern int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pcikbd_getkeycode(unsigned int scancode); -extern int pcikbd_pretranslate(unsigned char scancode, char raw_mode); extern int pcikbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pcikbd_unexpected_up(unsigned char keycode); @@ -28,7 +27,6 @@ #define kbd_setkeycode pcikbd_setkeycode #define kbd_getkeycode pcikbd_getkeycode -#define kbd_pretranslate pcikbd_pretranslate #define kbd_translate pcikbd_translate #define kbd_unexpected_up pcikbd_unexpected_up #define kbd_leds pcikbd_leds diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/namei.h linux/include/asm-sparc/namei.h --- v2.2.6/linux/include/asm-sparc/namei.h Thu Nov 19 09:56:29 1998 +++ linux/include/asm-sparc/namei.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.12 1998/10/28 08:13:42 jj Exp $ +/* $Id: namei.h,v 1.13 1999/04/06 06:54:36 jj Exp $ * linux/include/asm-sparc/namei.h * * Routines to handle famous /usr/gnemul/s*. @@ -18,11 +18,8 @@ char *emul; switch (current->personality) { -#if 0 -/* Until we solve, why SunOS apps sometime crash, disable gnemul support for SunOS */ case PER_BSD: emul = SPARC_BSD_EMUL; break; -#endif case PER_SVR4: emul = SPARC_SOL_EMUL; break; default: diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/siginfo.h linux/include/asm-sparc/siginfo.h --- v2.2.6/linux/include/asm-sparc/siginfo.h Mon Oct 5 13:13:43 1998 +++ linux/include/asm-sparc/siginfo.h Mon Apr 26 15:55:54 1999 @@ -142,7 +142,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h --- v2.2.6/linux/include/asm-sparc/softirq.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc/softirq.h Thu Apr 22 19:24:52 1999 @@ -1,21 +1,23 @@ /* softirq.h: 32-bit Sparc soft IRQ support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) */ #ifndef __SPARC_SOFTIRQ_H #define __SPARC_SOFTIRQ_H +#include /* For NR_CPUS */ + #include #include #include -extern unsigned int local_bh_count[NR_CPUS]; #define get_active_bhs() (bh_mask & bh_active) #ifdef __SMP__ +extern unsigned int local_bh_count[NR_CPUS]; /* * The locking mechanism for base handlers, to prevent re-entrancy, @@ -23,7 +25,7 @@ * referenced at all outside of this file. */ extern atomic_t global_bh_lock; -extern atomic_t global_bh_count; +extern spinlock_t global_bh_count; extern spinlock_t sparc_bh_lock; extern void synchronize_bh(void); @@ -100,30 +102,31 @@ /* These are for the IRQs testing the lock */ static inline int softirq_trylock(int cpu) { - if (atomic_add_return(1, &global_bh_count) == 1) { + if (spin_trylock(&global_bh_count)) { if (atomic_read(&global_bh_lock) == 0) { ++local_bh_count[cpu]; return 1; } + spin_unlock(&global_bh_count); } - atomic_dec(&global_bh_count); return 0; } static inline void softirq_endlock(int cpu) { local_bh_count[cpu]--; - atomic_dec(&global_bh_count); + spin_unlock(&global_bh_count); } #else +extern unsigned int local_bh_count; #define clear_active_bhs(x) (bh_active &= ~(x)) #define mark_bh(nr) (bh_active |= (1 << (nr))) /* These are for the irq's testing the lock */ -#define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1)) -#define softirq_endlock(cpu) (local_bh_count[cpu] = 0) +#define softirq_trylock(cpu) (local_bh_count ? 0 : (local_bh_count=1)) +#define softirq_endlock(cpu) (local_bh_count = 0) #define synchronize_bh() barrier() /* @@ -153,19 +156,20 @@ extern inline void remove_bh(int nr) { bh_mask &= ~(1 << nr); + mb(); bh_base[nr] = NULL; } extern inline void start_bh_atomic(void) { - local_bh_count[0]++; + local_bh_count++; barrier(); } extern inline void end_bh_atomic(void) { barrier(); - local_bh_count[0]--; + local_bh_count--; } #endif /* SMP */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h --- v2.2.6/linux/include/asm-sparc/spinlock.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc/spinlock.h Thu Apr 22 19:24:52 1999 @@ -6,6 +6,8 @@ #ifndef __SPARC_SPINLOCK_H #define __SPARC_SPINLOCK_H +#include /* For NR_CPUS */ + #ifndef __ASSEMBLY__ #ifndef __SMP__ @@ -67,6 +69,7 @@ #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0 } #define spin_lock_init(lp) do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0) +#define spin_is_locked(lp) (*((volatile unsigned char *)(&((lp)->lock))) != 0) #define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock)) extern void _do_spin_lock(spinlock_t *lock, char *str); @@ -86,7 +89,7 @@ struct _rwlock_debug { volatile unsigned int lock; unsigned long owner_pc; - unsigned long reader_pc[NCPUS]; + unsigned long reader_pc[NR_CPUS]; }; typedef struct _rwlock_debug rwlock_t; @@ -139,7 +142,8 @@ #define SPIN_LOCK_UNLOCKED 0 #define spin_lock_init(lock) (*(lock) = 0) -#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile spinlock_t *)lock) +#define spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0) +#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile unsigned char *)lock) extern __inline__ void spin_lock(spinlock_t *lock) { diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h --- v2.2.6/linux/include/asm-sparc/system.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc/system.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.72 1999/01/02 16:50:21 davem Exp $ */ +/* $Id: system.h,v 1.73 1999/04/20 13:22:49 anton Exp $ */ #include #ifndef __SPARC_SYSTEM_H @@ -47,6 +47,8 @@ #define ARCH_SUN4C_SUN4 1 #define ARCH_SUN4 1 #endif + +#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */ extern unsigned long empty_bad_page; extern unsigned long empty_bad_page_table; diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h --- v2.2.6/linux/include/asm-sparc/timer.h Mon Oct 5 13:13:43 1998 +++ linux/include/asm-sparc/timer.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: timer.h,v 1.20 1998/09/21 05:07:37 jj Exp $ +/* $Id: timer.h,v 1.21 1999/04/20 13:22:51 anton Exp $ * timer.h: Definitions for the timer chips on the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -9,7 +9,7 @@ #ifndef _SPARC_TIMER_H #define _SPARC_TIMER_H -#include /* For NCPUS */ +#include /* For SUN4M_NCPUS */ #include #include @@ -70,7 +70,7 @@ }; struct sun4m_timer_regs { - struct sun4m_timer_percpu_info cpu_timers[NCPUS]; + struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS]; volatile unsigned int l10_timer_limit; volatile unsigned int l10_cur_count; diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h --- v2.2.6/linux/include/asm-sparc/uaccess.h Mon Oct 5 13:13:43 1998 +++ linux/include/asm-sparc/uaccess.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.17 1998/09/16 12:25:29 jj Exp $ +/* $Id: uaccess.h,v 1.18 1999/03/30 06:38:38 jj Exp $ * uaccess.h: User space memore access functions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -349,9 +349,8 @@ .align 4 .word 1f,3 .previous -1: mov %2, %%o1 - call __bzero +1: call __bzero mov %1, %%o0 mov %%o0, %0 " : "=r" (ret) : "r" (addr), "r" (size) : diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h --- v2.2.6/linux/include/asm-sparc/unistd.h Mon Mar 29 11:09:12 1999 +++ linux/include/asm-sparc/unistd.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: unistd.h,v 1.54 1999/03/25 00:40:12 davem Exp $ */ +/* $Id: unistd.h,v 1.55 1999/04/07 17:14:15 davem Exp $ */ #ifndef _SPARC_UNISTD_H #define _SPARC_UNISTD_H @@ -60,7 +60,7 @@ #define __NR_pipe 42 /* Common */ #define __NR_times 43 /* Implemented via getrusage() in SunOS */ /* #define __NR_profil 44 Common */ -/* #define __NR_ni_syscall 45 ENOSYS under SunOS */ +#define __NR_umount2 45 /* Linux Specific */ #define __NR_setgid 46 /* Implemented via setregid() in SunOS */ #define __NR_getgid 47 /* Common */ #define __NR_signal 48 /* Implemented via sigvec() in SunOS */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h --- v2.2.6/linux/include/asm-sparc/vaddrs.h Sat Nov 9 00:30:26 1996 +++ linux/include/asm-sparc/vaddrs.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: vaddrs.h,v 1.21 1996/10/07 03:03:02 davem Exp $ */ +/* $Id: vaddrs.h,v 1.22 1999/04/20 13:22:55 anton Exp $ */ #ifndef _SPARC_VADDRS_H #define _SPARC_VADDRS_H @@ -51,7 +51,7 @@ /* On sun4m machines we need per-cpu virtual areas */ #define PERCPU_VADDR 0xffc00000 /* Base for per-cpu virtual mappings */ #define PERCPU_ENTSIZE 0x00100000 -#define PERCPU_LEN ((PERCPU_ENTSIZE*NCPUS)) +#define PERCPU_LEN ((PERCPU_ENTSIZE*SUN4M_NCPUS)) /* per-cpu offsets */ #define PERCPU_TBR_OFFSET 0x00000 /* %tbr, mainly used for identification. */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h --- v2.2.6/linux/include/asm-sparc64/ide.h Mon Oct 5 13:13:44 1998 +++ linux/include/asm-sparc64/ide.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ide.h,v 1.11 1998/08/12 22:19:37 ecd Exp $ +/* $Id: ide.h,v 1.12 1999/04/17 14:25:29 davem Exp $ * ide.h: Ultra/PCI specific IDE glue. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -123,7 +123,7 @@ unsigned long count) { volatile unsigned short *data_port; - unsigned long end = (unsigned long)dst + count; + unsigned long end = (unsigned long)dst + (count << 1); u16 *ps = dst; u32 *pi; @@ -154,7 +154,7 @@ unsigned long count) { volatile unsigned short *data_port; - unsigned long end = (unsigned long)src + count; + unsigned long end = (unsigned long)src + (count << 1); const u16 *ps = src; const u32 *pi; diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/keyboard.h linux/include/asm-sparc64/keyboard.h --- v2.2.6/linux/include/asm-sparc64/keyboard.h Mon Jan 12 15:15:58 1998 +++ linux/include/asm-sparc64/keyboard.h Wed Apr 28 08:47:39 1999 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.2 1997/09/07 15:40:49 ecd Exp $ +/* $Id: keyboard.h,v 1.3 1999/04/28 11:59:12 davem Exp $ * linux/include/asm-sparc64/keyboard.h * * Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) @@ -18,7 +18,6 @@ extern int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pcikbd_getkeycode(unsigned int scancode); -extern int pcikbd_pretranslate(unsigned char scancode, char raw_mode); extern int pcikbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pcikbd_unexpected_up(unsigned char keycode); @@ -28,7 +27,6 @@ #define kbd_setkeycode pcikbd_setkeycode #define kbd_getkeycode pcikbd_getkeycode -#define kbd_pretranslate pcikbd_pretranslate #define kbd_translate pcikbd_translate #define kbd_unexpected_up pcikbd_unexpected_up #define kbd_leds pcikbd_leds diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/namei.h linux/include/asm-sparc64/namei.h --- v2.2.6/linux/include/asm-sparc64/namei.h Thu Nov 19 09:56:29 1998 +++ linux/include/asm-sparc64/namei.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.13 1998/10/28 08:13:49 jj Exp $ +/* $Id: namei.h,v 1.14 1999/04/06 06:54:39 jj Exp $ * linux/include/asm-sparc64/namei.h * * Routines to handle famous /usr/gnemul/s*. @@ -18,11 +18,8 @@ char *emul; switch (current->personality) { -#if 0 -/* Until we solve, why SunOS apps sometime crash, disable gnemul support for SunOS */ case PER_BSD: emul = SPARC_BSD_EMUL; break; -#endif case PER_SVR4: emul = SPARC_SOL_EMUL; break; default: diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/psycho.h linux/include/asm-sparc64/psycho.h --- v2.2.6/linux/include/asm-sparc64/psycho.h Tue Mar 23 14:35:48 1999 +++ linux/include/asm-sparc64/psycho.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: psycho.h,v 1.4 1998/12/23 10:08:16 davem Exp $ +/* $Id: psycho.h,v 1.5 1999/04/01 12:27:28 davem Exp $ * psycho.h: UltraSparc AX specific PCI definitions. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -257,7 +257,7 @@ #define PSYCHO_CEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ #define PSYCHO_CEAFSR_RESV1 0x0300000000000000 /* Reserved */ #define PSYCHO_CEAFSR_ESYND 0x00ff000000000000 /* Syndrome Bits */ -#define PSYCHO_UEAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_CEAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ #define PSYCHO_CEAFSR_DOFF 0x00000000e0000000 /* Double Offset */ #define PSYCHO_CEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */ #define PSYCHO_CEAFSR_BLK 0x0000000000800000 /* Trans was block operation */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/siginfo.h linux/include/asm-sparc64/siginfo.h --- v2.2.6/linux/include/asm-sparc64/siginfo.h Thu Aug 20 17:05:18 1998 +++ linux/include/asm-sparc64/siginfo.h Mon Apr 26 15:55:54 1999 @@ -201,7 +201,7 @@ */ #define TRAP_BRKPT 1 /* process breakpoint */ #define TRAP_TRACE 2 /* process trace trap */ -#define NSIGTRAP +#define NSIGTRAP 2 /* * SIGCHLD si_codes diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h --- v2.2.6/linux/include/asm-sparc64/ttable.h Mon Oct 5 13:13:44 1998 +++ linux/include/asm-sparc64/ttable.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ttable.h,v 1.10 1998/09/25 01:09:45 davem Exp $ */ +/* $Id: ttable.h,v 1.11 1999/03/29 12:38:12 jj Exp $ */ #ifndef _SPARC64_TTABLE_H #define _SPARC64_TTABLE_H @@ -29,11 +29,21 @@ clr %l6; \ nop; +#define TRAP_SAVEFPU(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, do_fptrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; \ + nop; + #define TRAP_NOSAVE(routine) \ ba,pt %xcc, routine; \ nop; \ nop; nop; nop; nop; nop; nop; - + #define TRAPTL1(routine) \ sethi %hi(109f), %g7; \ ba,pt %xcc, etraptl1; \ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h --- v2.2.6/linux/include/asm-sparc64/unistd.h Mon Mar 29 11:09:12 1999 +++ linux/include/asm-sparc64/unistd.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: unistd.h,v 1.27 1999/03/25 00:40:14 davem Exp $ */ +/* $Id: unistd.h,v 1.28 1999/04/07 17:14:19 davem Exp $ */ #ifndef _SPARC64_UNISTD_H #define _SPARC64_UNISTD_H @@ -60,7 +60,7 @@ #define __NR_pipe 42 /* Common */ #define __NR_times 43 /* Implemented via getrusage() in SunOS */ /* #define __NR_profil 44 Common */ -/* #define __NR_ni_syscall 45 ENOSYS under SunOS */ +#define __NR_umount2 45 /* Linux Specific */ #define __NR_setgid 46 /* Implemented via setregid() in SunOS */ #define __NR_getgid 47 /* Common */ #define __NR_signal 48 /* Implemented via sigvec() in SunOS */ diff -u --recursive --new-file v2.2.6/linux/include/asm-sparc64/visasm.h linux/include/asm-sparc64/visasm.h --- v2.2.6/linux/include/asm-sparc64/visasm.h Mon Oct 5 13:13:44 1998 +++ linux/include/asm-sparc64/visasm.h Thu Apr 22 19:24:52 1999 @@ -1,4 +1,4 @@ -/* $Id: visasm.h,v 1.3 1998/09/04 01:59:48 ecd Exp $ */ +/* $Id: visasm.h,v 1.4 1999/04/19 01:25:55 davem Exp $ */ #ifndef _SPARC64_VISASM_H #define _SPARC64_VISASM_H @@ -10,7 +10,7 @@ #include #include -#define AOFF_task_fpregs (((ASIZ_task) + 255) & ~255) +#define AOFF_task_fpregs (((ASIZ_task) + (64 - 1)) & ~(64 - 1)) /* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc */ diff -u --recursive --new-file v2.2.6/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h --- v2.2.6/linux/include/linux/adfs_fs.h Fri Jul 31 17:05:52 1998 +++ linux/include/linux/adfs_fs.h Fri Apr 23 21:20:38 1999 @@ -155,7 +155,7 @@ extern int adfs_map_lookup (struct super_block *sb, int frag_id, int offset); /* namei.c */ -extern int adfs_lookup (struct inode *dir, struct dentry *dentry); +extern struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry); /* super.c */ extern int init_adfs_fs (void); diff -u --recursive --new-file v2.2.6/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h --- v2.2.6/linux/include/linux/affs_fs.h Fri Jul 31 17:10:57 1998 +++ linux/include/linux/affs_fs.h Fri Apr 23 21:20:38 1999 @@ -60,7 +60,7 @@ /* namei.c */ extern int affs_hash_name(const unsigned char *name, int len, int intl, int hashsize); -extern int affs_lookup(struct inode *dir, struct dentry *dentry); +extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry); extern int affs_unlink(struct inode *dir, struct dentry *dentry); extern int affs_create(struct inode *dir, struct dentry *dentry, int mode); extern int affs_mkdir(struct inode *dir, struct dentry *dentry, int mode); diff -u --recursive --new-file v2.2.6/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.2.6/linux/include/linux/ext2_fs.h Mon Sep 28 10:51:35 1998 +++ linux/include/linux/ext2_fs.h Fri Apr 23 21:20:38 1999 @@ -572,7 +572,7 @@ /* namei.c */ extern void ext2_release (struct inode *, struct file *); -extern int ext2_lookup (struct inode *, struct dentry *); +extern struct dentry *ext2_lookup (struct inode *, struct dentry *); extern int ext2_create (struct inode *,struct dentry *,int); extern int ext2_mkdir (struct inode *,struct dentry *,int); extern int ext2_rmdir (struct inode *,struct dentry *); diff -u --recursive --new-file v2.2.6/linux/include/linux/fb.h linux/include/linux/fb.h --- v2.2.6/linux/include/linux/fb.h Wed Mar 10 15:29:50 1999 +++ linux/include/linux/fb.h Sat Apr 24 17:51:48 1999 @@ -31,6 +31,7 @@ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ #define FB_TYPE_TEXT 3 /* Text/attributes */ +#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ #define FB_AUX_TEXT_MDA 0 /* Monochrome text */ #define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ @@ -236,6 +237,8 @@ unsigned long arg, int con, struct fb_info *info); /* perform fb specific mmap */ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); + /* switch to/from raster image mode */ + int (*fb_rasterimg)(struct fb_info *info, int start); }; @@ -295,7 +298,7 @@ struct fb_info { char modename[40]; /* default video mode */ - int node; + kdev_t node; int flags; #define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */ struct fb_ops *fbops; diff -u --recursive --new-file v2.2.6/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.2.6/linux/include/linux/fs.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/fs.h Tue Apr 27 09:56:21 1999 @@ -169,7 +169,7 @@ extern void update_atime (struct inode *inode); #define UPDATE_ATIME(inode) update_atime (inode) -extern void buffer_init(void); +extern void buffer_init(unsigned long); extern void inode_init(void); extern void file_table_init(void); extern void dcache_init(void); @@ -254,18 +254,8 @@ return test_bit(BH_Protected, &bh->b_state); } -/* - * Deprecated - we don't keep per-buffer reference flags - * any more. - * - * We _could_ try to update the page reference, but that - * doesn't seem to really be worth it either. If we did, - * it would look something like this: - * - * #define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) - * #define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) - */ -#define touch_buffer(bh) do { } while (0) +#define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) +#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) #include #include @@ -607,7 +597,7 @@ struct inode_operations { struct file_operations * default_file_ops; int (*create) (struct inode *,struct dentry *,int); - int (*lookup) (struct inode *,struct dentry *); + struct dentry * (*lookup) (struct inode *,struct dentry *); int (*link) (struct dentry *,struct inode *,struct dentry *); int (*unlink) (struct inode *,struct dentry *); int (*symlink) (struct inode *,struct dentry *,const char *); diff -u --recursive --new-file v2.2.6/linux/include/linux/if_ppp.h linux/include/linux/if_ppp.h --- v2.2.6/linux/include/linux/if_ppp.h Thu Jul 16 18:09:29 1998 +++ linux/include/linux/if_ppp.h Tue Apr 27 00:38:28 1999 @@ -1,4 +1,4 @@ -/* $Id: if_ppp.h,v 1.14 1998/07/07 04:27:33 paulus Exp $ */ +/* $Id: if_ppp.h,v 1.19 1999/03/31 06:07:57 paulus Exp $ */ /* * if_ppp.h - Point-to-Point Protocol definitions. @@ -21,7 +21,7 @@ */ /* - * ==FILEVERSION 980704== + * ==FILEVERSION 990331== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -35,19 +35,13 @@ #ifndef _IF_PPP_H_ #define _IF_PPP_H_ -#if defined(__linux__) -#include -#include -#include -#endif - /* * Packet sizes */ #define PPP_MTU 1500 /* Default MTU (size of Info field) */ #define PPP_MAXMRU 65000 /* Largest MRU we allow */ -#define PPP_VERSION "2.3.3" +#define PPP_VERSION "2.3.7" #define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ #define PROTO_IPX 0x002b /* protocol numbers */ #define PROTO_DNA_RT 0x0027 /* DNA Routing */ @@ -73,7 +67,8 @@ #define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ -#define SC_MASK 0x0f0000ff /* bits that user can change */ +#define SC_SYNC 0x00200000 /* synchronous serial mode */ +#define SC_MASK 0x0f2000ff /* bits that user can change */ /* state bits */ #define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */ diff -u --recursive --new-file v2.2.6/linux/include/linux/if_pppvar.h linux/include/linux/if_pppvar.h --- v2.2.6/linux/include/linux/if_pppvar.h Tue Jan 19 11:32:53 1999 +++ linux/include/linux/if_pppvar.h Tue Apr 27 00:38:28 1999 @@ -42,7 +42,7 @@ */ /* - * ==FILEVERSION 990114== + * ==FILEVERSION 990325== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -89,6 +89,7 @@ __u8 escape; /* 0x20 if prev char was PPP_ESC */ __u8 toss; /* toss this frame */ volatile __u8 tty_pushing; /* internal state flag */ + volatile __u8 woke_up; /* internal state flag */ __u32 xmit_async_map[8]; /* 1 bit means that given control character is quoted on output*/ __u32 recv_async_map; /* 1 bit means that given control diff -u --recursive --new-file v2.2.6/linux/include/linux/in6.h linux/include/linux/in6.h --- v2.2.6/linux/include/linux/in6.h Mon Oct 5 13:13:44 1998 +++ linux/include/linux/in6.h Thu Apr 22 19:45:19 1999 @@ -67,6 +67,33 @@ int ipv6mr_ifindex; }; +struct in6_flowlabel_req +{ + struct in6_addr flr_dst; + __u32 flr_label; + __u8 flr_action; + __u8 flr_share; + __u16 flr_flags; + __u16 flr_expires; + __u16 flr_linger; + __u32 __flr_pad; + /* Options in format of IPV6_PKTOPTIONS */ +}; + +#define IPV6_FL_A_GET 0 +#define IPV6_FL_A_PUT 1 +#define IPV6_FL_A_RENEW 2 + +#define IPV6_FL_F_CREATE 1 +#define IPV6_FL_F_EXCL 2 + +#define IPV6_FL_S_NONE 0 +#define IPV6_FL_S_EXCL 1 +#define IPV6_FL_S_PROCESS 2 +#define IPV6_FL_S_USER 3 +#define IPV6_FL_S_ANY 255 + + /* * Bitmask constant declarations to help applications select out the * flow label and priority fields. @@ -75,9 +102,10 @@ * sockaddr_in6 is in network byte order. */ -#define IPV6_FLOWINFO_FLOWLABEL 0x00ff -#define IPV6_FLOWINFO_PRIORITY 0x0f00 +#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff +#define IPV6_FLOWINFO_PRIORITY 0x0ff00000 +/* These defintions are obsolete */ #define IPV6_PRIORITY_UNCHARACTERIZED 0x0000 #define IPV6_PRIORITY_FILLER 0x0100 #define IPV6_PRIORITY_UNATTENDED 0x0200 @@ -129,6 +157,7 @@ #define IPV6_HOPLIMIT 8 #define IPV6_NEXTHOP 9 #define IPV6_AUTHHDR 10 +#define IPV6_FLOWINFO 11 #if 0 /* Aliases for obsolete names */ @@ -157,5 +186,10 @@ #define IPV6_PMTUDISC_DONT 0 #define IPV6_PMTUDISC_WANT 1 #define IPV6_PMTUDISC_DO 2 + +/* Flowlabel */ +#define IPV6_FLOWLABEL_MGR 32 +#define IPV6_FLOWINFO_SEND 33 + #endif diff -u --recursive --new-file v2.2.6/linux/include/linux/irda.h linux/include/linux/irda.h --- v2.2.6/linux/include/linux/irda.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/irda.h Sat Apr 24 17:49:37 1999 @@ -0,0 +1,120 @@ +/********************************************************************* + * + * Filename: irda.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Mar 8 14:06:12 1999 + * Modified at: Mon Mar 22 14:14:54 1999 + * Modified by: Dag Brattli + * + * Copyright (c) 1999 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef KERNEL_IRDA_H +#define KERNEL_IRDA_H + +/* Hint bit positions for first hint byte */ +#define HINT_PNP 0x01 +#define HINT_PDA 0x02 +#define HINT_COMPUTER 0x04 +#define HINT_PRINTER 0x08 +#define HINT_MODEM 0x10 +#define HINT_FAX 0x20 +#define HINT_LAN 0x40 +#define HINT_EXTENSION 0x80 + +/* Hint bit positions for second hint byte (first extension byte) */ +#define HINT_TELEPHONY 0x01 +#define HINT_FILE_SERVER 0x02 +#define HINT_COMM 0x04 +#define HINT_MESSAGE 0x08 +#define HINT_HTTP 0x10 +#define HINT_OBEX 0x20 + +/* IrLMP character code values */ +#define CS_ASCII 0x00 +#define CS_ISO_8859_1 0x01 +#define CS_ISO_8859_2 0x02 +#define CS_ISO_8859_3 0x03 +#define CS_ISO_8859_4 0x04 +#define CS_ISO_8859_5 0x05 +#define CS_ISO_8859_6 0x06 +#define CS_ISO_8859_7 0x07 +#define CS_ISO_8859_8 0x08 +#define CS_ISO_8859_9 0x09 +#define CS_UNICODE 0xff + +#define SOL_IRLMP 266 /* Same as SOL_IRDA for now */ +#define SOL_IRTTP 266 /* Same as SOL_IRDA for now */ + +#define IRLMP_ENUMDEVICES 1 +#define IRLMP_IAS_SET 2 +#define IRLMP_IAS_QUERY 3 +#define IRLMP_DISCOVERY_MASK_SET 4 + +#define IRTTP_QOS_SET 5 +#define IRTTP_QOS_GET 6 +#define IRTTP_MAX_SDU_SIZE 7 + +#define IAS_MAX_STRING 256 +#define IAS_MAX_OCTET_STRING 1024 +#define IAS_MAX_CLASSNAME 64 +#define IAS_MAX_ATTRIBNAME 256 + +#define LSAP_ANY 0xff + +struct sockaddr_irda { + sa_family_t sir_family; /* AF_IRDA */ + unsigned char sir_lsap_sel; /* LSAP/TSAP selector */ + unsigned int sir_addr; /* Device address */ + char sir_name[25]; /* Usually :IrDA:TinyTP */ +}; + +struct irda_device_info { + unsigned int saddr; /* Address of remote device */ + unsigned int daddr; /* Link where it was discovered */ + char info[22]; /* Description */ + unsigned char charset; /* Charset used for description */ + unsigned char hints[2]; /* Hint bits */ +}; + +struct irda_device_list { + unsigned int len; + struct irda_device_info dev[0]; +}; + +struct irda_ias_set { + char irda_class_name[IAS_MAX_CLASSNAME]; + char irda_attrib_name[IAS_MAX_ATTRIBNAME]; + unsigned int irda_attrib_type; + union { + unsigned int irda_attrib_int; + struct { + unsigned short len; + u_char OctetSeq[IAS_MAX_OCTET_STRING]; + } irda_attrib_octet_seq; + struct { + unsigned char len; + unsigned char charset; + unsigned char string[IAS_MAX_STRING]; + } irda_attrib_string; + } attribute; +}; + +#endif /* KERNEL_IRDA_H */ + + + + diff -u --recursive --new-file v2.2.6/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h --- v2.2.6/linux/include/linux/iso_fs.h Fri Jul 31 17:09:42 1998 +++ linux/include/linux/iso_fs.h Fri Apr 23 21:20:38 1999 @@ -189,7 +189,7 @@ extern int isofs_open(struct inode * inode, struct file * filp); extern void isofs_release(struct inode * inode, struct file * filp); -extern int isofs_lookup(struct inode * dir, struct dentry *); +extern struct dentry *isofs_lookup(struct inode * dir, struct dentry *); extern unsigned long isofs_count_free_inodes(struct super_block *sb); extern int isofs_new_block(int dev); extern int isofs_free_block(int dev, int block); diff -u --recursive --new-file v2.2.6/linux/include/linux/kbd_ll.h linux/include/linux/kbd_ll.h --- v2.2.6/linux/include/linux/kbd_ll.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/kbd_ll.h Mon Apr 26 13:22:33 1999 @@ -7,6 +7,6 @@ extern struct pt_regs *kbd_pt_regs; -void handle_scancode(unsigned char scancode); +void handle_scancode(unsigned char scancode, int down); #endif /* _KBD_LL_H */ diff -u --recursive --new-file v2.2.6/linux/include/linux/minix_fs.h linux/include/linux/minix_fs.h --- v2.2.6/linux/include/linux/minix_fs.h Fri Nov 27 13:09:29 1998 +++ linux/include/linux/minix_fs.h Fri Apr 23 21:20:38 1999 @@ -89,7 +89,7 @@ #ifdef __KERNEL__ -extern int minix_lookup(struct inode * dir, struct dentry *dentry); +extern struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry); extern int minix_create(struct inode * dir, struct dentry *dentry, int mode); extern int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode); extern int minix_rmdir(struct inode * dir, struct dentry *dentry); diff -u --recursive --new-file v2.2.6/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h --- v2.2.6/linux/include/linux/msdos_fs.h Fri Jul 31 17:10:57 1998 +++ linux/include/linux/msdos_fs.h Tue Apr 27 09:58:11 1999 @@ -195,7 +195,7 @@ }; /* misc.c */ -extern int is_binary(char conversion,char *extension); +extern int fat_is_binary(char conversion,char *extension); extern void lock_fat(struct super_block *sb); extern void unlock_fat(struct super_block *sb); extern int fat_add_cluster(struct inode *inode); @@ -271,7 +271,7 @@ /* msdos.c - these are for Umsdos */ extern void msdos_read_inode(struct inode *inode); -extern int msdos_lookup(struct inode *dir,struct dentry *); +extern struct dentry *msdos_lookup(struct inode *dir,struct dentry *); extern int msdos_create(struct inode *dir,struct dentry *dentry,int mode); extern int msdos_rmdir(struct inode *dir,struct dentry *dentry); extern int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode); @@ -312,7 +312,7 @@ extern struct super_block *vfat_read_super(struct super_block *sb,void *data, int silent); extern void vfat_read_inode(struct inode *inode); -extern int vfat_lookup(struct inode *dir,struct dentry *); +extern struct dentry *vfat_lookup(struct inode *dir,struct dentry *); /* vfat/vfatfs_syms.c */ extern struct file_system_type vfat_fs_type; diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp.h linux/include/linux/ncp.h --- v2.2.6/linux/include/linux/ncp.h Fri Jul 31 17:10:57 1998 +++ linux/include/linux/ncp.h Tue Apr 27 09:58:13 1999 @@ -3,6 +3,7 @@ * * Copyright (C) 1995 by Volker Lendecke * Modified for sparc by J.F. Chadima + * Modified for __constant_ntoh by Frank A. Vorstenbosch * */ @@ -58,11 +59,21 @@ /* these define the attribute byte as seen by NCP */ #define aRONLY (ntohl(0x01000000)) -#define aHIDDEN (ntohl(0x02000000)) -#define aSYSTEM (ntohl(0x04000000)) +#define aHIDDEN (__constant_ntohl(0x02000000)) +#define aSYSTEM (__constant_ntohl(0x04000000)) #define aEXECUTE (ntohl(0x08000000)) #define aDIR (ntohl(0x10000000)) #define aARCH (ntohl(0x20000000)) +#define aSHARED (ntohl(0x80000000)) +#define aDONTSUBALLOCATE (ntohl(1L<<(11+8))) +#define aTRANSACTIONAL (ntohl(1L<<(12+8))) +#define aPURGE (ntohl(1L<<(16-8))) +#define aRENAMEINHIBIT (ntohl(1L<<(17-8))) +#define aDELETEINHIBIT (ntohl(1L<<(18-8))) +#define aDONTCOMPRESS (nothl(1L<<(27-24))) + +#define NCP_MIN_SYMLINK_SIZE 8 +#define NCP_MAX_SYMLINK_SIZE 512 #define AR_READ (ntohs(0x0100)) #define AR_WRITE (ntohs(0x0200)) diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h --- v2.2.6/linux/include/linux/ncp_fs.h Fri Jul 31 17:11:03 1998 +++ linux/include/linux/ncp_fs.h Tue Apr 27 09:58:24 1999 @@ -13,6 +13,15 @@ #include #include + +/* NLS charsets by ioctl */ +#define NCP_IOCSNAME_LEN 20 +struct ncp_nls_ioctl +{ + unsigned char codepage[NCP_IOCSNAME_LEN+1]; + unsigned char iocharset[NCP_IOCSNAME_LEN+1]; +}; + #include #include @@ -111,6 +120,9 @@ #define NCP_IOC_GETPRIVATEDATA _IOWR('n', 10, struct ncp_privatedata_ioctl) #define NCP_IOC_SETPRIVATEDATA _IOR('n', 10, struct ncp_privatedata_ioctl) +#define NCP_IOC_GETCHARSETS _IOWR('n', 11, struct ncp_nls_ioctl) +#define NCP_IOC_SETCHARSETS _IOR('n', 11, struct ncp_nls_ioctl) + /* * The packet size to allocate. One page should be enough. */ @@ -155,6 +167,12 @@ __u32 dirEntNum __attribute__((packed)); __u32 DosDirNum __attribute__((packed)); __u32 volNumber __attribute__((packed)); +#ifdef CONFIG_NCPFS_SMALLDOS + __u32 origNS; +#endif +#ifdef CONFIG_NCPFS_STRONG + __u32 nwattr; +#endif int opened; int access; __u32 server_file_handle __attribute__((packed)); @@ -272,11 +290,14 @@ return server->name_space[NCP_FINFO(inode)->volNumber]; } -static inline int ncp_preserve_case(struct inode *i) -{ +static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) { #if defined(CONFIG_NCPFS_NFS_NS) || defined(CONFIG_NCPFS_OS2_NS) int ns = ncp_namespace(i); #endif +#if defined(CONFIG_NCPFS_SMALLDOS) && defined(CONFIG_NCPFS_OS2_NS) + if ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) + return 0; +#endif return #ifdef CONFIG_NCPFS_OS2_NS (ns == NW_NS_OS2) || @@ -285,6 +306,11 @@ (ns == NW_NS_NFS) || #endif /* CONFIG_NCPFS_NFS_NS */ 0; +} + +static inline int ncp_preserve_case(struct inode *i) +{ + return ncp_preserve_entry_case(i, NW_NS_OS2); } static inline int ncp_case_sensitive(struct inode *i) diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h --- v2.2.6/linux/include/linux/ncp_fs_sb.h Fri Jul 31 17:11:03 1998 +++ linux/include/linux/ncp_fs_sb.h Tue Apr 27 09:58:24 1999 @@ -73,6 +73,10 @@ size_t len; void* data; } priv; + + struct ncp_nls_ioctl nls_charsets; /* NLS user data */ + struct nls_table *nls_vol; /* codepage used on volume */ + struct nls_table *nls_io; /* charset used for input and display */ }; static inline int ncp_conn_valid(struct ncp_server *server) diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_mount.h linux/include/linux/ncp_mount.h --- v2.2.6/linux/include/linux/ncp_mount.h Fri Jul 31 17:11:03 1998 +++ linux/include/linux/ncp_mount.h Tue Apr 27 09:58:23 1999 @@ -16,11 +16,13 @@ #define NCP_MOUNT_VERSION 3 /* Values for flags */ -#define NCP_MOUNT_SOFT 0x0001 -#define NCP_MOUNT_INTR 0x0002 -#define NCP_MOUNT_STRONG 0x0004 /* enable delete/rename of r/o files */ -#define NCP_MOUNT_NO_OS2 0x0008 -#define NCP_MOUNT_NO_NFS 0x0010 +#define NCP_MOUNT_SOFT 0x0001 +#define NCP_MOUNT_INTR 0x0002 +#define NCP_MOUNT_STRONG 0x0004 /* enable delete/rename of r/o files */ +#define NCP_MOUNT_NO_OS2 0x0008 /* do not use OS/2 (LONG) namespace */ +#define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */ +#define NCP_MOUNT_EXTRAS 0x0020 +#define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */ struct ncp_mount_data { int version; diff -u --recursive --new-file v2.2.6/linux/include/linux/pagemap.h linux/include/linux/pagemap.h --- v2.2.6/linux/include/linux/pagemap.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/pagemap.h Tue Apr 27 09:56:34 1999 @@ -20,8 +20,6 @@ #define PAGE_HASH_BITS 12 #define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS) -#define PAGE_AGE_VALUE 16 - extern unsigned long page_cache_size; /* # of pages currently in the hash table */ extern struct page * page_hash_table[PAGE_HASH_SIZE]; diff -u --recursive --new-file v2.2.6/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.2.6/linux/include/linux/pci.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/pci.h Tue Apr 27 09:56:21 1999 @@ -927,6 +927,9 @@ #define PCI_VENDOR_ID_CCUBE 0x123f +#define PCI_VENDOR_ID_AVM 0x1244 +#define PCI_DEVICE_ID_AVM_A1 0x0a00 + #define PCI_VENDOR_ID_DIPIX 0x1246 #define PCI_VENDOR_ID_STALLION 0x124d diff -u --recursive --new-file v2.2.6/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.2.6/linux/include/linux/proc_fs.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/proc_fs.h Wed Apr 28 08:47:39 1999 @@ -382,7 +382,7 @@ * of the /proc/ subdirectories. */ extern int proc_readdir(struct file *, void *, filldir_t); -extern int proc_lookup(struct inode *, struct dentry *); +extern struct dentry *proc_lookup(struct inode *, struct dentry *); struct openpromfs_dev { struct openpromfs_dev *next; @@ -394,7 +394,7 @@ }; extern struct inode_operations * proc_openprom_register(int (*readdir)(struct file *, void *, filldir_t), - int (*lookup)(struct inode *, struct dentry *), + struct dentry * (*lookup)(struct inode *, struct dentry *), void (*use)(struct inode *, int), struct openpromfs_dev ***); extern void proc_openprom_deregister(void); diff -u --recursive --new-file v2.2.6/linux/include/linux/qnx4_fs.h linux/include/linux/qnx4_fs.h --- v2.2.6/linux/include/linux/qnx4_fs.h Sat Sep 5 16:46:41 1998 +++ linux/include/linux/qnx4_fs.h Fri Apr 23 21:20:38 1999 @@ -95,7 +95,7 @@ #define QNX4DEBUG(X) (void) 0 #endif -extern int qnx4_lookup(struct inode *dir, struct dentry *dentry); +extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry); extern unsigned long qnx4_count_free_inodes(struct super_block *sb); extern unsigned long qnx4_count_free_blocks(struct super_block *sb); diff -u --recursive --new-file v2.2.6/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.2.6/linux/include/linux/sysctl.h Tue Mar 23 14:35:48 1999 +++ linux/include/linux/sysctl.h Sat Apr 24 12:47:47 1999 @@ -56,9 +56,15 @@ CTL_PROC=4, /* Process info */ CTL_FS=5, /* Filesystems */ CTL_DEBUG=6, /* Debugging */ - CTL_DEV=7 /* Devices */ + CTL_DEV=7, /* Devices */ + CTL_BUS=8 /* Buses */ }; +/* CTL_BUS names: */ +enum +{ + BUS_ISA=1 /* ISA */ +}; /* CTL_KERN names: */ enum @@ -133,9 +139,17 @@ NET_IPV6=12, NET_X25=13, NET_TR=14, - NET_DECNET=15 + NET_DECNET=15, + NET_ECONET=16 }; +/* /proc/sys/bus/isa */ +enum +{ + BUS_ISA_MEM_BASE=1, + BUS_ISA_PORT_BASE=2, + BUS_ISA_PORT_SHIFT=3 +}; /* /proc/sys/net/core */ enum diff -u --recursive --new-file v2.2.6/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h --- v2.2.6/linux/include/linux/sysv_fs.h Tue Mar 23 14:35:48 1999 +++ linux/include/linux/sysv_fs.h Tue Apr 27 09:58:12 1999 @@ -367,7 +367,7 @@ * Function prototypes */ -extern int sysv_lookup(struct inode * dir, struct dentry * dentry); +extern struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry); extern int sysv_create(struct inode * dir, struct dentry * dentry, int mode); extern int sysv_mkdir(struct inode * dir, struct dentry * dentry, int mode); extern int sysv_rmdir(struct inode * dir, struct dentry * dentry); diff -u --recursive --new-file v2.2.6/linux/include/linux/ufs_fs.h linux/include/linux/ufs_fs.h --- v2.2.6/linux/include/linux/ufs_fs.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/ufs_fs.h Fri Apr 23 21:20:38 1999 @@ -540,7 +540,7 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); /* namei.c */ -extern int ufs_lookup (struct inode *, struct dentry *); +extern struct dentry *ufs_lookup (struct inode *, struct dentry *); extern int ufs_mkdir(struct inode *, struct dentry *, int); extern int ufs_rmdir (struct inode *, struct dentry *); extern int ufs_unlink (struct inode *, struct dentry *); diff -u --recursive --new-file v2.2.6/linux/include/linux/umsdos_fs.p linux/include/linux/umsdos_fs.p --- v2.2.6/linux/include/linux/umsdos_fs.p Fri Apr 16 14:47:31 1999 +++ linux/include/linux/umsdos_fs.p Fri Apr 23 21:20:38 1999 @@ -9,8 +9,8 @@ char * umsdos_d_path(struct dentry *, char *, int); void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *); int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry); -int umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo); -int UMSDOS_lookup(struct inode *, struct dentry *); +struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo); +struct dentry *UMSDOS_lookup(struct inode *, struct dentry *); struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int); struct dentry *umsdos_covered(struct dentry *, char *, int); @@ -106,8 +106,8 @@ struct dentry *new_dentry); /* rdir.c 22/03/95 03.31.42 */ -int umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo); -int UMSDOS_rlookup (struct inode *dir, struct dentry *dentry); +struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo); +struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry); /* symlink.c 23/01/95 03.38.30 */ diff -u --recursive --new-file v2.2.6/linux/include/linux/wireless.h linux/include/linux/wireless.h --- v2.2.6/linux/include/linux/wireless.h Tue Mar 23 14:35:48 1999 +++ linux/include/linux/wireless.h Sat Apr 24 17:51:48 1999 @@ -1,7 +1,7 @@ /* * This file define a set of standard wireless extensions * - * Version : 6 18.2.99 + * Version : 7 23.4.99 * * Authors : Jean Tourrilhes - HPLB - */ @@ -85,7 +85,11 @@ * * V5 to V6 * -------- - * - 802.11 support + * - 802.11 support (ESSID ioctls) + * + * V6 to V7 + * -------- + * - define IW_ESSID_MAX_SIZE and IW_MAX_AP */ /* -------------------------- IOCTL LIST -------------------------- */ @@ -123,6 +127,7 @@ /* As the ESSID is a string up to 32 bytes long, it doesn't fit within the * 'iwreq' structure, so we need to use the 'data' member to point to a * string in user space, like it is done for RANGE... + * The "flags" member indicate if the ESSID is active or not. */ /* ------------------------- IOCTL STUFF ------------------------- */ @@ -169,6 +174,13 @@ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 +/* Maximum of address that you may get in the + list of access points in range */ +#define IW_MAX_AP 8 + +/* Maximum size of the ESSID string */ +#define IW_ESSID_MAX_SIZE 32 + /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ @@ -278,7 +290,7 @@ caddr_t pointer; /* Pointer to the data * (in user space) */ __u16 length; /* fields or byte size */ - __u16 flags; /* Unused */ + __u16 flags; /* Optional params */ } data; } u; }; diff -u --recursive --new-file v2.2.6/linux/include/net/dst.h linux/include/net/dst.h --- v2.2.6/linux/include/net/dst.h Tue Mar 23 14:35:48 1999 +++ linux/include/net/dst.h Tue Apr 27 09:57:25 1999 @@ -16,11 +16,7 @@ * 1 - rare events and bugs (default) * 2 - trace mode. */ -#ifdef NO_ANK_FIX #define RT_CACHE_DEBUG 0 -#else -#define RT_CACHE_DEBUG 1 -#endif #define DST_GC_MIN (1*HZ) #define DST_GC_INC (5*HZ) diff -u --recursive --new-file v2.2.6/linux/include/net/flow.h linux/include/net/flow.h --- v2.2.6/linux/include/net/flow.h Sat Sep 5 16:46:41 1998 +++ linux/include/net/flow.h Thu Apr 22 19:45:19 1999 @@ -19,10 +19,12 @@ struct { struct in6_addr * daddr; struct in6_addr * saddr; + __u32 flowlabel; } ip6_u; } nl_u; #define fl6_dst nl_u.ip6_u.daddr #define fl6_src nl_u.ip6_u.saddr +#define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl4_dst nl_u.ip4_u.daddr #define fl4_src nl_u.ip4_u.saddr diff -u --recursive --new-file v2.2.6/linux/include/net/ipv6.h linux/include/net/ipv6.h --- v2.2.6/linux/include/net/ipv6.h Tue Mar 23 14:35:48 1999 +++ linux/include/net/ipv6.h Tue Apr 27 09:57:29 1999 @@ -4,7 +4,7 @@ * Authors: * Pedro Roque * - * $Id: ipv6.h,v 1.15 1999/03/21 05:22:16 davem Exp $ + * $Id: ipv6.h,v 1.16 1999/04/22 10:07:27 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -124,6 +124,43 @@ /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ }; +struct ip6_flowlabel +{ + struct ip6_flowlabel *next; + u32 label; + struct in6_addr dst; + struct ipv6_txoptions *opt; + atomic_t users; + u32 linger; + u8 share; + u32 owner; + unsigned long lastuse; + unsigned long expires; +}; + +#define IPV6_FLOWINFO_MASK __constant_htonl(0x0FFFFFFF) +#define IPV6_FLOWLABEL_MASK __constant_htonl(0x000FFFFF) + +struct ipv6_fl_socklist +{ + struct ipv6_fl_socklist *next; + struct ip6_flowlabel *fl; +}; + +extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, u32 label); +extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, + struct ip6_flowlabel * fl, + struct ipv6_txoptions * fopt); +extern void fl6_free_socklist(struct sock *sk); +extern int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen); +extern void ip6_flowlabel_init(void); +extern void ip6_flowlabel_cleanup(void); + +extern __inline__ void fl6_sock_release(struct ip6_flowlabel *fl) +{ + if (fl) + atomic_dec(&fl->users); +} extern int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)); diff -u --recursive --new-file v2.2.6/linux/include/net/irda/discovery.h linux/include/net/irda/discovery.h --- v2.2.6/linux/include/net/irda/discovery.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/discovery.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Apr 6 16:53:53 1999 - * Modified at: Tue Apr 6 20:44:35 1999 + * Modified at: Thu Apr 22 11:04:56 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -37,6 +37,7 @@ #include #define DISCOVERY_EXPIRE_TIMEOUT 6*HZ +#define DISCOVERY_DEFAULT_SLOTS 0 /* * The DISCOVERY structure is used for both discovery requests and responses diff -u --recursive --new-file v2.2.6/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h --- v2.2.6/linux/include/net/irda/ircomm_common.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/ircomm_common.h Sat Apr 24 17:50:05 1999 @@ -28,8 +28,12 @@ #include typedef enum { - COMM_DISCOVERY, COMM_IDLE, + + COMM_DISCOVERY_WAIT, + COMM_QUERYPARAM_WAIT, + COMM_QUERYLSAP_WAIT, + COMM_WAITI, COMM_WAITR, COMM_CONN, @@ -53,6 +57,12 @@ IRCOMM_DATA_REQUEST, LMP_DATA_INDICATION, IRCOMM_CONTROL_REQUEST, + + DISCOVERY_INDICATION, + GOT_PARAMETERS, + GOT_LSAPSEL, + QUERYIAS_ERROR, + } IRCOMM_EVENT; typedef enum { @@ -172,6 +182,9 @@ __u32 daddr; /* Device address of the peer device */ __u32 saddr; + __u32 skey; + __u32 ckey; + int queryias_lock; int ias_type; int disconnect_priority; /* P_NORMAL or P_HIGH. see irttp.h */ struct notify_t notify; /* container of callbacks */ @@ -206,6 +219,7 @@ __u8 peer_port_type; __u8 servicetype; + __u8 peer_servicetype; __u8 data_format; __u8 peer_data_format; __u8 flow_ctrl; @@ -241,8 +255,7 @@ -int ircomm_query_ias_and_connect(struct ircomm_cb *self, __u8 servicetype); -void ircomm_connect_request(struct ircomm_cb *self); +void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype); void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, __u32 maxsdusize); void ircomm_disconnect_request(struct ircomm_cb *self, diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irda.h linux/include/net/irda/irda.h --- v2.2.6/linux/include/net/irda/irda.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irda.h Tue Apr 27 09:57:25 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:13:12 1997 - * Modified at: Tue Apr 6 20:31:08 1999 + * Modified at: Wed Apr 21 17:49:00 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -43,14 +43,15 @@ #define ALIGN __attribute__((aligned)) #define PACK __attribute__((packed)) -/* use 0 for production, 1 for verification, >2 for debug */ + #ifdef CONFIG_IRDA_DEBUG extern __u32 irda_debug; -#define IRDA_DEBUG 0 +/* use 0 for production, 1 for verification, >2 for debug */ +#define IRDA_DEBUG_LEVEL 0 -#define DEBUG(n, args...) if (irda_debug >= (n)) printk( KERN_DEBUG args) +#define DEBUG(n, args...) if (irda_debug >= (n)) printk(KERN_DEBUG args) #define ASSERT(expr, func) \ if(!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n",\ @@ -61,6 +62,12 @@ #define ASSERT(expr, func) #endif /* CONFIG_IRDA_DEBUG */ +#define WARNING(args...) printk(KERN_WARNING args) +#define MESSAGE(args...) printk(KERN_INFO args) +#define ERROR(args...) printk(KERN_ERR args) + +#define MSECS_TO_JIFFIES(ms) (ms*HZ/1000) + /* * Magic numbers used by Linux/IR. Random numbers which must be unique to * give the best protection @@ -111,6 +118,8 @@ __u32 skey; /* IrLMP service handle */ int nslots; /* Number of slots to use for discovery */ + + int errno; struct sock *sk; struct wait_queue *ias_wait; /* Wait for LM-IAS answer */ diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h --- v2.2.6/linux/include/net/irda/irda_device.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irda_device.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Haris Zukanovic * Created at: Tue Apr 14 12:41:42 1998 - * Modified at: Wed Apr 7 17:17:16 1999 + * Modified at: Tue Apr 20 11:06:28 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Haris Zukanovic, @@ -36,15 +36,18 @@ #include #include #include +#include /* Some non-standard interface flags (should not conflict with any in if.h) */ -#define IFF_SIR 0x01 /* Supports SIR speeds */ -#define IFF_MIR 0x02 /* Supports MIR speeds */ -#define IFF_FIR 0x04 /* Supports FIR speeds */ -#define IFF_PIO 0x08 /* Supports PIO transfer of data */ -#define IFF_DMA 0x10 /* Supports DMA transfer of data */ -#define IFF_SHM 0x20 /* Supports shared memory data transfers */ -#define IFF_DONGLE 0x40 /* Interface has a dongle attached */ +#define IFF_SIR 0x0001 /* Supports SIR speeds */ +#define IFF_MIR 0x0002 /* Supports MIR speeds */ +#define IFF_FIR 0x0004 /* Supports FIR speeds */ +#define IFF_VFIR 0x0008 /* Supports VFIR speeds */ +#define IFF_PIO 0x0010 /* Supports PIO transfer of data */ +#define IFF_DMA 0x0020 /* Supports DMA transfer of data */ +#define IFF_SHM 0x0040 /* Supports shared memory data transfers */ +#define IFF_DONGLE 0x0080 /* Interface has a dongle attached */ +#define IFF_AIR 0x0100 /* Supports A(dvanced)IR standards */ #define IO_XMIT 0x01 #define IO_RECV 0x02 @@ -65,18 +68,17 @@ int dongle_id; /* Dongle or transceiver currently used */ }; -/* Buffer specific info */ +/* IO buffer specific info (inspired by struct sk_buff) */ struct iobuff_t { int state; /* Receiving state (transmit state not used) */ int in_frame; /* True if receiving frame */ - __u8 *data; /* the buffer */ - __u8 *head; /* start of data in buffer */ + __u8 *head; /* start of buffer */ + __u8 *data; /* start of data in buffer */ __u8 *tail; /* end of data in buffer */ - int offset; /* Usually data + offset = head */ - int len; /* currently used bytes in buffer */ - int truesize; /* total size of the data area */ + int len; /* length of data */ + int truesize; /* total size of buffer */ __u16 fcs; int flags; /* Allocation flags (GFP_KERNEL | GFP_DMA ) */ @@ -89,7 +91,7 @@ * stuff from IrDA port implementations. */ struct irda_device { - QUEUE q; /* Must be first */ + QUEUE q; /* Must be first */ int magic; /* Our magic bullet */ char name[16]; /* Name of device "irda0" */ @@ -109,18 +111,18 @@ struct iobuff_t tx_buff; struct iobuff_t rx_buff; - int xbofs; - int media_busy; /* spinlock_t lock; */ /* For serializing operations */ /* Media busy stuff */ + int media_busy; struct timer_list media_busy_timer; - /* Driver specific implementation */ + /* Callbacks for driver specific implementation */ void (*change_speed)(struct irda_device *driver, int baud); - int (*is_receiving)(struct irda_device *); /* receiving? */ + int (*is_receiving)(struct irda_device *); /* receiving? */ /* int (*is_tbusy)(struct irda_device *); */ /* transmitting? */ void (*wait_until_sent)(struct irda_device *); + void (*set_caddr)(struct irda_device *); /* Set connection addr */ }; extern hashbin_t *irda_device; @@ -143,8 +145,28 @@ int irda_device_setup(struct device *dev); -inline unsigned short irda_get_mtt(struct sk_buff *skb); - void setup_dma(int channel, char *buffer, int count, int mode); +/* + * Function irda_get_mtt (skb) + * + * Utility function for getting the minimum turnaround time out of + * the skb, where it has been hidden in the cb field. + */ +inline static __u16 irda_get_mtt(struct sk_buff *skb) +{ + __u16 mtt; + + if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) + mtt = 10000; + else + mtt = ((struct irlap_skb_cb *)(skb->cb))->mtt; + + ASSERT(mtt <= 10000, return 10000;); + + return mtt; +} + #endif + + diff -u --recursive --new-file v2.2.6/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h --- v2.2.6/linux/include/net/irda/iriap.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/iriap.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Mon Mar 22 13:15:04 1999 + * Modified at: Wed Apr 21 16:37:21 1999 * Modified by: Dag Brattli * * Copyright (c) 1997 Dag Brattli , All Rights Reserved. @@ -51,9 +51,10 @@ #define IAS_SUCCESS 0 #define IAS_CLASS_UNKNOWN 1 #define IAS_ATTRIB_UNKNOWN 2 +#define IAS_DISCONNECT 10 -typedef void (*CONFIRM_CALLBACK)( __u16 obj_id, struct ias_value *value, - void *priv); +typedef void (*CONFIRM_CALLBACK)(int result, __u16 obj_id, + struct ias_value *value, void *priv); struct iriap_cb { QUEUE queue; /* Must be first */ diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irkbd.h linux/include/net/irda/irkbd.h --- v2.2.6/linux/include/net/irda/irkbd.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irkbd.h Wed Dec 31 16:00:00 1969 @@ -1,91 +0,0 @@ -/********************************************************************* - * - * Filename: irkbd.h - * Version: 0.2 - * Description: IrDA Keyboard/Mouse driver (Tekram IR-660) - * Status: Experimental. - * Author: Dag Brattli - * Created at: Mon Mar 1 00:24:19 1999 - * Modified at: Thu Mar 11 14:54:00 1999 - * Modified by: Dag Brattli - * - * Copyright (c) 1999 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * Neither Dag Brattli nor University of Tromsø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - ********************************************************************/ - -#ifndef IRKBD_H -#define IRKBD_H - -/* Some commands */ -#define IRKBD_CMD_INIT_KBD 0xfe -#define IRKBD_CMD_INIT_MOUSE 0xff -#define IRKBD_CMD_ENABLE 0x41 -#define IRKBD_CMD_LED 0x31 -#define IRKBD_CMD_KDB_SPEED 0x33 - -/* Some responses */ -#define IRKBD_RSP_KBDOK 0x11 -#define IRKBD_RSP_KBDERR 0x12 -#define IRKBD_RSP_MSOK 0x21 -#define IRKBD_RSP_MSERR 0x22 -#define IRKBD_RSP_LEDOK 0x31 -#define IRKBD_RSP_KBDSPEEDOK 0x33 -#define IRKBD_RSP_RSPN41 0x41 - -#define IRKBD_RATE 2 /* Polling rate, should be 15 ms */ -#define IRKBD_TIMEOUT 100 /* 1000 ms */ - -#define SUBFRAME_MASK 0xc0 -#define SUBFRAME_MOUSE 0x80 -#define SUBFRAME_KEYBOARD 0x40 -#define SUBFRAME_RESPONSE 0x00 - -#define IRKBD_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) - -#define IRKBD_BUF_SIZE 4096 /* Must be power of 2! */ - -enum { - IRKBD_IDLE, /* Not connected */ - IRKBD_INIT_KBD, /* Initializing keyboard */ - IRKBD_INIT_MOUSE, /* Initializing mouse */ - IRKBD_POLLING, /* Polling device */ -}; - -/* Main structure */ -struct irkbd_cb { - struct miscdevice dev; - char devname[9]; /* name of the registered device */ - int state; - - int count; /* Open count */ - - __u32 saddr; /* my local address */ - __u32 daddr; /* peer address */ - - struct tsap_cb *tsap; - __u8 dtsap_sel; /* remote TSAP address */ - __u8 stsap_sel; /* local TSAP address */ - - struct timer_list watchdog_timer; - - LOCAL_FLOW tx_flow; - LOCAL_FLOW rx_flow; - - __u8 scancodes[IRKBD_BUF_SIZE]; /* Buffer for mouse events */ - int head; - int tail; - - struct wait_queue *read_wait; - struct fasync_struct *async; -}; - -#endif /* IRKBD_H */ diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlan_client.h linux/include/net/irda/irlan_client.h --- v2.2.6/linux/include/net/irda/irlan_client.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlan_client.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Feb 25 21:05:53 1999 + * Modified at: Thu Apr 22 14:13:34 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -30,6 +30,7 @@ #include #include +#include #include void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout); @@ -38,7 +39,7 @@ void irlan_client_open_ctrl_tsap( struct irlan_cb *self); -void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb); -void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, - void *priv); +void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb); +void irlan_client_get_value_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv); #endif diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h --- v2.2.6/linux/include/net/irda/irlan_common.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlan_common.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Tue Apr 6 16:19:41 1999 + * Modified at: Thu Apr 22 14:30:37 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -121,7 +121,6 @@ int broadcast_open; struct timer_list kick_timer; - int start_new_provider; }; /* @@ -183,6 +182,10 @@ struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev); void irlan_close(struct irlan_cb *self); +void irlan_close_tsaps(struct irlan_cb *self); +void irlan_mod_inc_use_count(void); +void irlan_mod_dec_use_count(void); + int irlan_register_netdev(struct irlan_cb *self); void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel); void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout); @@ -204,7 +207,7 @@ int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value, __u16 value_len); -int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len); +int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len); void print_ret_code(__u8 code); extern hashbin_t *irlan; diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlan_eth.h linux/include/net/irda/irlan_eth.h --- v2.2.6/linux/include/net/irda/irlan_eth.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlan_eth.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Oct 15 08:36:58 1998 - * Modified at: Mon Mar 22 12:57:11 1999 + * Modified at: Thu Apr 22 14:09:37 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -25,6 +25,9 @@ #ifndef IRLAN_ETH_H #define IRLAN_ETH_H +int irlan_eth_init(struct device *dev); +int irlan_eth_open(struct device *dev); +int irlan_eth_close(struct device *dev); int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb); int irlan_eth_xmit(struct sk_buff *skb, struct device *dev); diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlan_provider.h linux/include/net/irda/irlan_provider.h --- v2.2.6/linux/include/net/irda/irlan_provider.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlan_provider.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Mon Mar 8 15:32:35 1999 + * Modified at: Thu Apr 22 14:29:16 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -46,12 +46,12 @@ void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *); int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb); -int irlan_provider_extract_params(struct irlan_cb *self, int cmd, - struct sk_buff *skb); +int irlan_provider_parse_command(struct irlan_cb *self, int cmd, + struct sk_buff *skb); void irlan_provider_send_reply(struct irlan_cb *self, int command, int ret_code); -void irlan_provider_open_ctrl_tsap( struct irlan_cb *self); +int irlan_provider_open_ctrl_tsap(struct irlan_cb *self); #endif diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h --- v2.2.6/linux/include/net/irda/irlap.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlap.h Sat Apr 24 17:50:05 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Mar 26 15:15:17 1999 + * Modified at: Fri Apr 23 09:51:15 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -219,12 +219,12 @@ int irlap_generate_rand_time_slot( int S, int s); void irlap_initiate_connection_state( struct irlap_cb *); -void irlap_flush_all_queues( struct irlap_cb *); -void irlap_change_speed( struct irlap_cb *, int); -void irlap_wait_min_turn_around( struct irlap_cb *, struct qos_info *); - -void irlap_init_qos_capabilities( struct irlap_cb *, struct qos_info *); -void irlap_apply_default_connection_parameters( struct irlap_cb *self); -void irlap_apply_connection_parameters( struct irlap_cb *, struct qos_info *); +void irlap_flush_all_queues(struct irlap_cb *); +void irlap_change_speed(struct irlap_cb *, int); +void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *); + +void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *); +void irlap_apply_default_connection_parameters(struct irlap_cb *self); +void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *); #endif diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h --- v2.2.6/linux/include/net/irda/irlap_frame.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlap_frame.h Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 10:27:26 1997 - * Modified at: Fri Mar 26 14:10:53 1999 + * Modified at: Fri Apr 23 09:33:55 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -116,8 +116,6 @@ int vs; /* next frame to send */ int vr; /* next frame to receive */ }; - -__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb); void irlap_send_discovery_xid_frame( struct irlap_cb *, int S, __u8 s, __u8 command, discovery_t *discovery); diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h --- v2.2.6/linux/include/net/irda/irlmp.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irlmp.h Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Tue Apr 6 20:05:14 1999 + * Modified at: Fri Apr 23 09:15:07 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -202,12 +202,12 @@ void irlmp_register_link(struct irlap_cb *, __u32 saddr, struct notify_t *); void irlmp_unregister_link(__u32 saddr); -int irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, - __u32 saddr, __u32 daddr, - struct qos_info *, struct sk_buff *); -void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb); -void irlmp_connect_response( struct lsap_cb *, struct sk_buff *); -void irlmp_connect_confirm( struct lsap_cb *, struct sk_buff *); +int irlmp_connect_request(struct lsap_cb *, __u8 dlsap_sel, + __u32 saddr, __u32 daddr, + struct qos_info *, struct sk_buff *); +void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb); +void irlmp_connect_response(struct lsap_cb *, struct sk_buff *); +void irlmp_connect_confirm(struct lsap_cb *, struct sk_buff *); struct lsap_cb *irlmp_dup(struct lsap_cb *self, void *instance); void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, @@ -219,17 +219,17 @@ void irlmp_do_discovery(int nslots); discovery_t *irlmp_get_discovery_response(void); -void irlmp_data_request( struct lsap_cb *, struct sk_buff *); -void irlmp_udata_request( struct lsap_cb *, struct sk_buff *); -void irlmp_data_indication( struct lsap_cb *, struct sk_buff *); -void irlmp_udata_indication( struct lsap_cb *, struct sk_buff *); +void irlmp_data_request(struct lsap_cb *, struct sk_buff *); +inline void irlmp_udata_request(struct lsap_cb *, struct sk_buff *); +inline void irlmp_data_indication(struct lsap_cb *, struct sk_buff *); +inline void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *); void irlmp_status_request(void); -void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock); +void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock); -int irlmp_slsap_inuse( __u8 slsap); +int irlmp_slsap_inuse(__u8 slsap); __u8 irlmp_find_free_slsap(void); -LM_REASON irlmp_convert_lap_reason( LAP_REASON); +LM_REASON irlmp_convert_lap_reason(LAP_REASON); __u32 irlmp_get_saddr(struct lsap_cb *self); __u32 irlmp_get_daddr(struct lsap_cb *self); diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irlpt_cli.h linux/include/net/irda/irlpt_cli.h --- v2.2.6/linux/include/net/irda/irlpt_cli.h Wed Mar 10 15:29:50 1999 +++ linux/include/net/irda/irlpt_cli.h Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Mon Jan 11 15:58:16 1999 + * Modified at: Wed Apr 21 16:46:26 1999 * Modified by: Dag Brattli * * Copyright (c) 1998, Thomas Davis, @@ -34,7 +34,7 @@ * if it's static, it doesn't go in here. */ -void irlpt_client_get_value_confirm(__u16 obj_id, +void irlpt_client_get_value_confirm(int result, __u16 obj_id, struct ias_value *value, void *priv); void irlpt_client_connect_indication( void *instance, diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h --- v2.2.6/linux/include/net/irda/irmod.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irmod.h Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Dec 15 13:58:52 1997 - * Modified at: Tue Mar 16 22:27:41 1999 + * Modified at: Fri Apr 9 11:13:39 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -101,7 +101,22 @@ int irmod_init_module(void); void irmod_cleanup_module(void); -inline int irda_lock(int *lock); +/* + * Function irda_lock (lock) + * + * Lock variable. Returns false if the lock is already set. + * + */ +static inline int irda_lock(int *lock) +{ + if (test_and_set_bit( 0, (void *) lock)) { + DEBUG(3, __FUNCTION__ + "(), Trying to lock, already locked variable!\n"); + return FALSE; + } + return TRUE; +} + inline int irda_unlock(int *lock); void irda_notify_init(struct notify_t *notify); diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irobex.h linux/include/net/irda/irobex.h --- v2.2.6/linux/include/net/irda/irobex.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irobex.h Wed Dec 31 16:00:00 1969 @@ -1,114 +0,0 @@ -/********************************************************************* - * - * Filename: irobex.h - * Version: 0.8 - * Description: - * Status: Experimental. - * Author: Dag Brattli - * Created at: Sat Jul 4 22:43:57 1998 - * Modified at: Thu Mar 11 16:11:54 1999 - * Modified by: Dag Brattli - * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * Neither Dag Brattli nor University of Tromsø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - ********************************************************************/ - -#ifndef IROBEX_H -#define IROBEX_H - -#include -#include -#include -#include - -#include -#include -#include - -#define LOW_THRESHOLD 4 -#define HIGH_THRESHOLD 8 -#define IROBEX_MAX_QUEUE 12 - -/* Small structure to be used by the IOCTL call */ -struct irobex_ioc_t { - __u32 daddr; -}; - -#define IROBEX_IOC_MAGIC 'k' - -#define IROBEX_IOCSCONNECT _IOW(IROBEX_IOC_MAGIC, 1, 4) -#define IROBEX_IOCSDISCONNECT _IOW(IROBEX_IOC_MAGIC, 2, 4) -#define IROBEX_IOC_MAXNR 2 - -#define IROBEX_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) - -typedef enum { - OBEX_IDLE, /* Doing nothing */ - OBEX_DISCOVER, /* Trying to discovery remote device */ - OBEX_QUERY, /* Querying remote LM-IAS */ - OBEX_CONN, /* Trying to connect to remote device */ - OBEX_DATA, /* Data transfer ready */ -} OBEX_STATE; - -struct irobex_cb { - QUEUE queue; /* Must be first! */ - - int magic; /* magic used to detect corruption of the struct */ - - OBEX_STATE state; /* Current state */ - - __u32 saddr; /* my local address */ - __u32 daddr; /* peer address */ - unsigned long time_discovered; - - __u32 ckey; /* IrLMP client handle */ - __u32 skey; /* IrLMP service handle */ - - char devname[9]; /* name of the registered device */ - struct tsap_cb *tsap; - int eof; - - __u8 dtsap_sel; /* remote TSAP address */ - __u8 stsap_sel; /* local TSAP address */ - - int irlap_data_size; - - struct miscdevice dev; - - int count; /* open count */ - - struct sk_buff_head rx_queue; /* Receive queue */ - - struct wait_queue *read_wait; - struct wait_queue *write_wait; - - struct fasync_struct *async; - - struct timer_list watchdog_timer; - - LOCAL_FLOW tx_flow; - LOCAL_FLOW rx_flow; -}; - -int irobex_init(void); - -void irobex_watchdog_timer_expired( unsigned long data); - -inline void irobex_start_watchdog_timer( struct irobex_cb *self, int timeout) -{ - irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self, - irobex_watchdog_timer_expired); -} - -extern struct irobex_cb *irobex; - -#endif diff -u --recursive --new-file v2.2.6/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h --- v2.2.6/linux/include/net/irda/irttp.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/irda/irttp.h Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Mon Mar 22 13:17:30 1999 + * Modified at: Sat Apr 10 10:19:56 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -93,7 +93,7 @@ __u32 rx_max_sdu_size; /* Max receive user data size */ int tx_sdu_busy; /* TxSdu.busy */ - int tx_max_sdu_size; /* Max transmit user data size */ + __u32 tx_max_sdu_size; /* Max transmit user data size */ int close_pend; /* Close, but disconnect_pend */ int disconnect_pend; /* Disconnect, but still data to send */ diff -u --recursive --new-file v2.2.6/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h --- v2.2.6/linux/include/net/pkt_sched.h Tue Mar 23 14:35:48 1999 +++ linux/include/net/pkt_sched.h Thu Apr 22 19:45:19 1999 @@ -215,6 +215,8 @@ (stamp) = __cur>>psched_clock_scale; \ }) +#define PSCHED_EXPORTLIST_1 + #elif defined (__alpha__) #define PSCHED_WATCHER u32 diff -u --recursive --new-file v2.2.6/linux/include/net/route.h linux/include/net/route.h --- v2.2.6/linux/include/net/route.h Tue Mar 23 14:35:48 1999 +++ linux/include/net/route.h Tue Apr 27 09:57:27 1999 @@ -114,6 +114,7 @@ extern int ip_route_output(struct rtable **, u32 dst, u32 src, u32 tos, int oif); extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct device *devin); extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu); +extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu); extern void ip_rt_send_redirect(struct sk_buff *skb); extern unsigned inet_addr_type(u32 addr); diff -u --recursive --new-file v2.2.6/linux/include/net/sock.h linux/include/net/sock.h --- v2.2.6/linux/include/net/sock.h Fri Apr 16 14:47:31 1999 +++ linux/include/net/sock.h Tue Apr 27 09:57:28 1999 @@ -146,12 +146,11 @@ struct in6_addr daddr; struct in6_addr *daddr_cache; - __u32 flow_lbl; + __u32 flow_label; __u32 frag_size; int hop_limit; int mcast_hops; int mcast_oif; - __u8 priority; /* pktoption flags */ union { @@ -162,7 +161,7 @@ hopopts:1, dstopts:1, authhdr:1, - unused:1; + rxflow:1; } bits; __u8 all; } rxopt; @@ -170,9 +169,11 @@ /* sockopt flags */ __u8 mc_loop:1, recverr:1, + sndflow:1, pmtudisc:2; struct ipv6_mc_socklist *ipv6_mc_list; + struct ipv6_fl_socklist *ipv6_fl_list; __u32 dst_cookie; struct ipv6_txoptions *opt; diff -u --recursive --new-file v2.2.6/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.2.6/linux/include/net/tcp.h Tue Mar 23 14:35:48 1999 +++ linux/include/net/tcp.h Wed Apr 28 09:51:57 1999 @@ -716,6 +716,14 @@ return (new_win && (new_win > (cur_win << 1))); } +/* TCP timestamps are only 32-bits, this causes a slight + * complication on 64-bit systems since we store a snapshot + * of jiffies in the buffer control blocks below. We decidely + * only use of the low 32-bits of jiffies and hide the ugly + * casts with the following macro. + */ +#define tcp_time_stamp ((__u32)(jiffies)) + /* This is what the send packet queueing engine uses to pass * TCP per-packet control information to the transmission * code. We also store the host-order sequence numbers in @@ -732,7 +740,7 @@ } header; /* For incoming frames */ __u32 seq; /* Starting sequence number */ __u32 end_seq; /* SEQ + FIN + SYN + datalen */ - unsigned long when; /* used to compute rtt's */ + __u32 when; /* used to compute rtt's */ __u8 flags; /* TCP header flags. */ /* NOTE: These must match up to the flags byte in a @@ -793,17 +801,22 @@ * c) We are retransmiting [Nagle] * d) We have too many packets 'in flight' * - * Don't use the nagle rule for urgent data. + * Don't use the nagle rule for urgent data (or + * for the final FIN -DaveM). */ if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) || (!sk->nonagle && skb->len < (tp->mss_cache >> 1) && tp->packets_out && - !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG))) + !(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN)))) nagle_check = 0; + /* Don't be strict about the congestion window for the + * final FIN frame. -DaveM + */ return (nagle_check && - (tcp_packets_in_flight(tp) < tp->snd_cwnd) && + ((tcp_packets_in_flight(tp) < tp->snd_cwnd) || + (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) && !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) && tp->retransmits == 0); } diff -u --recursive --new-file v2.2.6/linux/include/net/transp_v6.h linux/include/net/transp_v6.h --- v2.2.6/linux/include/net/transp_v6.h Sat Sep 5 16:46:42 1998 +++ linux/include/net/transp_v6.h Tue Apr 27 09:57:33 1999 @@ -13,6 +13,8 @@ extern struct proto udpv6_prot; extern struct proto tcpv6_prot; +struct flowi; + extern void rawv6_init(void); extern void udpv6_init(void); extern void tcpv6_init(void); @@ -26,8 +28,7 @@ struct sk_buff *skb); extern int datagram_send_ctl(struct msghdr *msg, - int *oif, - struct in6_addr **src_addr, + struct flowi *fl, struct ipv6_txoptions *opt, int *hlimit); diff -u --recursive --new-file v2.2.6/linux/init/main.c linux/init/main.c --- v2.2.6/linux/init/main.c Fri Apr 16 14:47:31 1999 +++ linux/init/main.c Sat Apr 24 17:51:48 1999 @@ -184,6 +184,7 @@ extern void u14_34f_setup(char *str, int *ints); extern void fdomain_setup(char *str, int *ints); extern void ibmmca_scsi_setup(char *str, int *ints); +extern void fd_mcs_setup(char *str, int *ints); extern void in2000_setup(char *str, int *ints); extern void NCR53c406a_setup(char *str, int *ints); extern void sym53c416_setup(char *str, int *ints); @@ -709,6 +710,9 @@ #ifdef CONFIG_SCSI_IBMMCA { "ibmmcascsi=", ibmmca_scsi_setup }, #endif +#ifdef CONFIG_SCSI_FD_MCS + { "fd_mcs=", fd_mcs_setup }, +#endif #if defined(CONFIG_SCSI_DC390T) && ! defined(CONFIG_SCSI_DC390T_NOGENSUPP) { "tmscsim=", dc390_setup }, #endif @@ -1166,7 +1170,7 @@ filescache_init(); dcache_init(); vma_init(); - buffer_init(); + buffer_init(memory_end-memory_start); signals_init(); inode_init(); file_table_init(); diff -u --recursive --new-file v2.2.6/linux/ipc/shm.c linux/ipc/shm.c --- v2.2.6/linux/ipc/shm.c Fri Apr 16 14:47:31 1999 +++ linux/ipc/shm.c Thu Apr 22 23:31:06 1999 @@ -691,10 +691,10 @@ next_id: swap_idx = 0; if (++swap_id > max_shmid) { + swap_id = 0; if (loop) goto failed; loop = 1; - swap_id = 0; } goto check_id; } diff -u --recursive --new-file v2.2.6/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.2.6/linux/mm/page_alloc.c Mon Jan 25 17:44:34 1999 +++ linux/mm/page_alloc.c Wed Apr 21 13:03:48 1999 @@ -33,7 +33,7 @@ for the ring buffers */ #define NR_MEM_LISTS 12 #else -#define NR_MEM_LISTS 6 +#define NR_MEM_LISTS 10 #endif /* The start of this MUST match the start of "struct page" */ diff -u --recursive --new-file v2.2.6/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v2.2.6/linux/mm/vmalloc.c Tue Jan 19 11:32:53 1999 +++ linux/mm/vmalloc.c Wed Apr 21 23:12:32 1999 @@ -161,11 +161,11 @@ for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { if (size + addr < (unsigned long) tmp->addr) break; + addr = tmp->size + (unsigned long) tmp->addr; if (addr > VMALLOC_END-size) { kfree(area); return NULL; } - addr = tmp->size + (unsigned long) tmp->addr; } area->addr = (void *)addr; area->size = size + PAGE_SIZE; diff -u --recursive --new-file v2.2.6/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.2.6/linux/mm/vmscan.c Tue Feb 23 15:21:35 1999 +++ linux/mm/vmscan.c Fri Apr 23 11:07:30 1999 @@ -45,12 +45,7 @@ page = pte_page(pte); if (MAP_NR(page) >= max_mapnr) return 0; - page_map = mem_map + MAP_NR(page); - if (PageReserved(page_map) - || PageLocked(page_map) - || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))) - return 0; if (pte_young(pte)) { /* @@ -62,6 +57,11 @@ return 0; } + if (PageReserved(page_map) + || PageLocked(page_map) + || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))) + return 0; + /* * Is the page already in the swap cache? If so, then * we can just drop our reference to it without doing @@ -248,9 +248,8 @@ pgd_t *pgdir; unsigned long end; - /* Don't swap out areas like shared memory which have their - own separate swapping mechanism or areas which are locked down */ - if (vma->vm_flags & (VM_SHM | VM_LOCKED)) + /* Don't swap out areas which are locked down */ + if (vma->vm_flags & VM_LOCKED) return 0; pgdir = pgd_offset(tsk->mm, address); diff -u --recursive --new-file v2.2.6/linux/net/802/tr.c linux/net/802/tr.c --- v2.2.6/linux/net/802/tr.c Tue Dec 22 14:16:59 1998 +++ linux/net/802/tr.c Sat Apr 24 17:51:48 1999 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -68,6 +67,8 @@ rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, }; +static spinlock_t rif_lock = SPIN_LOCK_UNLOCKED; + #define RIF_TIMEOUT 60*10*HZ #define RIF_CHECK_INTERVAL 60*HZ @@ -230,6 +231,9 @@ unsigned int hash; rif_cache entry; unsigned char *olddata; + unsigned long flags; + + spin_lock_irqsave(&rif_lock, flags); /* * Broadcasts are single route as stated in RFC 1042 @@ -298,6 +302,8 @@ else slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8); olddata = skb->data; + spin_unlock_irqrestore(&rif_lock, flags); + skb_pull(skb, slack); memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack); } @@ -312,7 +318,11 @@ int i; unsigned int hash, rii_p = 0; rif_cache entry; + unsigned long flags; + + spin_lock_irqsave(&rif_lock, flags); + /* * Firstly see if the entry exists */ @@ -350,6 +360,7 @@ if(!entry) { printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n"); + spin_unlock_irqrestore(&rif_lock, flags); return; } @@ -391,6 +402,7 @@ } entry->last_used=jiffies; } + spin_unlock_irqrestore(&rif_lock, flags); } /* @@ -402,9 +414,8 @@ int i; unsigned long now=jiffies,flags; - save_flags(flags); - cli(); - + spin_lock_irqsave(&rif_lock, flags); + for(i=0; i < RIF_TABLE_SIZE;i++) { rif_cache entry, *pentry=rif_table+i; @@ -422,7 +433,8 @@ pentry=&entry->next; } } - restore_flags(flags); + + spin_unlock_irqrestore(&rif_lock, flags); /* * Reset the timer diff -u --recursive --new-file v2.2.6/linux/net/core/neighbour.c linux/net/core/neighbour.c --- v2.2.6/linux/net/core/neighbour.c Mon Mar 29 11:09:12 1999 +++ linux/net/core/neighbour.c Thu Apr 22 19:45:19 1999 @@ -1170,7 +1170,7 @@ for (h=0; h <= NEIGH_HASHMASK; h++) { if (h < s_h) continue; if (h > s_h) - memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0])); + s_idx = 0; start_bh_atomic(); for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { @@ -1179,12 +1179,14 @@ if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH) <= 0) { end_bh_atomic(); - goto done; + cb->args[1] = h; + cb->args[2] = idx; + return -1; } } end_bh_atomic(); } -done: + cb->args[1] = h; cb->args[2] = idx; return skb->len; @@ -1355,10 +1357,10 @@ t->neigh_dev[0].ctl_name = dev->ifindex; memset(&t->neigh_vars[12], 0, sizeof(ctl_table)); } else { - t->neigh_vars[12].data = (&p->locktime) + 1; - t->neigh_vars[13].data = (&p->locktime) + 2; - t->neigh_vars[14].data = (&p->locktime) + 3; - t->neigh_vars[15].data = (&p->locktime) + 4; + t->neigh_vars[12].data = (int*)(p+1); + t->neigh_vars[13].data = (int*)(p+1) + 1; + t->neigh_vars[14].data = (int*)(p+1) + 2; + t->neigh_vars[15].data = (int*)(p+1) + 3; } t->neigh_neigh_dir[0].ctl_name = pdev_id; diff -u --recursive --new-file v2.2.6/linux/net/core/scm.c linux/net/core/scm.c --- v2.2.6/linux/net/core/scm.c Wed Mar 10 15:29:52 1999 +++ linux/net/core/scm.c Thu Apr 22 19:45:19 1999 @@ -122,7 +122,15 @@ err = -EINVAL; /* Verify that cmsg_len is at least sizeof(struct cmsghdr) */ - if ((unsigned long)(((char*)cmsg - (char*)msg->msg_control) + /* The first check was omitted in <= 2.2.5. The reasoning was + that parser checks cmsg_len in any case, so that + additional check would be work duplication. + But if cmsg_level is not SOL_SOCKET, we do not check + for too short ancillary data object at all! Oops. + OK, let's add it... + */ + if (cmsg->cmsg_len < sizeof(struct cmsghdr) || + (unsigned long)(((char*)cmsg - (char*)msg->msg_control) + cmsg->cmsg_len) > msg->msg_controllen) goto error; diff -u --recursive --new-file v2.2.6/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.2.6/linux/net/ipv4/af_inet.c Mon Mar 29 11:09:12 1999 +++ linux/net/ipv4/af_inet.c Thu Apr 22 19:45:19 1999 @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.86 1999/03/25 00:38:15 davem Exp $ + * Version: $Id: af_inet.c,v 1.87 1999/04/22 10:07:33 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -513,17 +513,6 @@ (sk->num != 0)) return -EINVAL; - snum = ntohs(addr->sin_port); -#ifdef CONFIG_IP_MASQUERADE - /* The kernel masquerader needs some ports. */ - if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END)) - return -EADDRINUSE; -#endif - if (snum == 0) - snum = sk->prot->good_socknum(); - if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) - return(-EACCES); - chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); if (addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) { @@ -545,6 +534,17 @@ if(chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ + snum = ntohs(addr->sin_port); +#ifdef CONFIG_IP_MASQUERADE + /* The kernel masquerader needs some ports. */ + if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END)) + return -EADDRINUSE; +#endif + if (snum == 0) + snum = sk->prot->good_socknum(); + if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return(-EACCES); + /* Make sure we are allowed to bind here. */ if(sk->prot->verify_bind(sk, snum)) return -EADDRINUSE; diff -u --recursive --new-file v2.2.6/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.2.6/linux/net/ipv4/ip_fw.c Wed Jan 13 15:00:44 1999 +++ linux/net/ipv4/ip_fw.c Thu Apr 22 19:45:19 1999 @@ -32,6 +32,8 @@ * 3-Jan-1999: Fixed serious procfs security hole -- users should never * be allowed to view the chains! * Marc Santoro + * 29-Jan-1999: Locally generated bogus IPs dealt with, rather than crash + * during dump_packet. --RR. */ /* @@ -1660,6 +1662,10 @@ int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb) { + /* Locally generated bogus packets by root. . */ + if (((struct iphdr *)phdr)->ihl * 4 < sizeof(struct iphdr) + || (*pskb)->len < sizeof(struct iphdr)) + return FW_ACCEPT; return ip_fw_check(phdr, dev->name, arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0); } diff -u --recursive --new-file v2.2.6/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c --- v2.2.6/linux/net/ipv4/ip_input.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/ip_input.c Thu Apr 22 19:45:19 1999 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.36 1999/03/21 05:22:38 davem Exp $ + * Version: $Id: ip_input.c,v 1.37 1999/04/22 10:38:36 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -253,7 +253,19 @@ * Do we need to de-masquerade this packet? */ { - int ret = ip_fw_demasquerade(&skb); + int ret; + /* + * Some masq modules can re-inject packets if + * bad configured. + */ + + if((IPCB(skb)->flags&IPSKB_MASQUERADED)) { + printk(KERN_DEBUG "ip_input(): demasq recursion detected. Check masq modules configuration\n"); + kfree_skb(skb); + return 0; + } + + ret = ip_fw_demasquerade(&skb); if (ret < 0) { kfree_skb(skb); return 0; diff -u --recursive --new-file v2.2.6/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c --- v2.2.6/linux/net/ipv4/ip_sockglue.c Mon Mar 29 11:09:12 1999 +++ linux/net/ipv4/ip_sockglue.c Thu Apr 22 19:45:19 1999 @@ -5,7 +5,7 @@ * * The IP to API glue. * - * Version: $Id: ip_sockglue.c,v 1.41 1999/03/25 10:04:29 davem Exp $ + * Version: $Id: ip_sockglue.c,v 1.42 1999/04/22 10:07:34 davem Exp $ * * Authors: see ip.c * @@ -150,7 +150,8 @@ struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { - if ((unsigned long)(((char*)cmsg - (char*)msg->msg_control) + if (cmsg->cmsg_len < sizeof(struct cmsghdr) || + (unsigned long)(((char*)cmsg - (char*)msg->msg_control) + cmsg->cmsg_len) > msg->msg_controllen) { return -EINVAL; } diff -u --recursive --new-file v2.2.6/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.2.6/linux/net/ipv4/route.c Mon Mar 29 11:09:12 1999 +++ linux/net/ipv4/route.c Thu Apr 22 19:45:19 1999 @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.65 1999/03/25 10:04:35 davem Exp $ + * Version: $Id: route.c,v 1.66 1999/04/22 10:07:35 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -281,6 +281,9 @@ if (atomic_read(&rth->u.dst.use)) return 0; + if (rth->u.dst.expires && (long)(rth->u.dst.expires - jiffies) <= 0) + return 1; + age = jiffies - rth->u.dst.lastuse; if (age <= tmo1 && !rt_fast_clean(rth)) return 0; @@ -305,7 +308,7 @@ while ((rth = *rthp) != NULL) { if (rth->u.dst.expires) { /* Entrie is expired even if it is in use */ - if ((long)(now - rth->u.dst.expires) < tmo) { + if ((long)(now - rth->u.dst.expires) <= 0) { tmo >>= 1; rthp = &rth->u.rt_next; continue; @@ -564,8 +567,11 @@ */ if (attempts-- > 0) { int saved_elasticity = ip_rt_gc_elasticity; + int saved_int = ip_rt_gc_min_interval; ip_rt_gc_elasticity = 1; + ip_rt_gc_min_interval = 0; rt_garbage_collect(); + ip_rt_gc_min_interval = saved_int; ip_rt_gc_elasticity = saved_elasticity; goto restart; } @@ -885,7 +891,16 @@ } } } - return est_mtu; + return est_mtu ? : new_mtu; +} + +void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu) +{ + if (dst->pmtu > mtu && mtu >= 68 && + !(dst->mxlock&(1<pmtu = mtu; + dst_set_expires(dst, ip_rt_mtu_expires); + } } static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32 cookie) @@ -1850,7 +1865,7 @@ for (h=0; h < RT_HASH_DIVISOR; h++) { if (h < s_h) continue; if (h > s_h) - memset(&cb->args[1], 0, sizeof(cb->args) - sizeof(cb->args[0])); + s_idx = 0; start_bh_atomic(); for (rt = rt_hash_table[h], idx = 0; rt; rt = rt->u.rt_next, idx++) { if (idx < s_idx) diff -u --recursive --new-file v2.2.6/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.2.6/linux/net/ipv4/tcp.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/tcp.c Thu Apr 22 19:45:19 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.139 1999/03/17 19:30:34 davem Exp $ + * Version: $Id: tcp.c,v 1.140 1999/04/22 10:34:31 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -772,7 +772,7 @@ iov++; while(seglen > 0) { - int copy, tmp, queue_it; + int copy, tmp, queue_it, psh; if (err) goto do_fault2; @@ -854,11 +854,14 @@ * being outside the window, it will be queued * for later rather than sent. */ + psh = 0; copy = tp->snd_wnd - (tp->snd_nxt - tp->snd_una); - if(copy > (tp->max_window >> 1)) + if(copy > (tp->max_window >> 1)) { copy = min(copy, mss_now); - else + psh = 1; + } else { copy = mss_now; + } if(copy > seglen) copy = seglen; @@ -906,7 +909,7 @@ /* Prepare control bits for TCP header creation engine. */ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | - (PSH_NEEDED ? + ((PSH_NEEDED || psh) ? TCPCB_FLAG_PSH : 0)); TCP_SKB_CB(skb)->sacked = 0; if (flags & MSG_OOB) { diff -u --recursive --new-file v2.2.6/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.2.6/linux/net/ipv4/tcp_input.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/tcp_input.c Wed Apr 28 09:51:57 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.159 1999/03/17 19:30:39 davem Exp $ + * Version: $Id: tcp_input.c,v 1.163 1999/04/28 16:08:05 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -97,7 +97,7 @@ static void tcp_delack_estimator(struct tcp_opt *tp) { if(tp->ato == 0) { - tp->lrcvtime = jiffies; + tp->lrcvtime = tcp_time_stamp; /* Help sender leave slow start quickly, * and also makes sure we do not take this @@ -106,9 +106,9 @@ tp->ato = 1; tcp_enter_quickack_mode(tp); } else { - int m = jiffies - tp->lrcvtime; + int m = tcp_time_stamp - tp->lrcvtime; - tp->lrcvtime = jiffies; + tp->lrcvtime = tcp_time_stamp; if(m <= 0) m = 1; if(m > tp->rto) @@ -231,7 +231,7 @@ */ if((s32)(tp->rcv_tsval - tp->ts_recent) >= 0) { tp->ts_recent = tp->rcv_tsval; - tp->ts_recent_stamp = jiffies; + tp->ts_recent_stamp = tcp_time_stamp; } } } @@ -241,7 +241,7 @@ extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len) { /* ts_recent must be younger than 24 days */ - return (((s32)(jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) || + return (((s32)(tcp_time_stamp - tp->ts_recent_stamp) >= PAWS_24DAYS) || (((s32)(tp->rcv_tsval - tp->ts_recent) < 0) && /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */ (len != (th->doff * 4)))); @@ -609,7 +609,7 @@ { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); struct sk_buff *skb; - unsigned long now = jiffies; + __u32 now = tcp_time_stamp; int acked = 0; /* If we are retransmitting, and this ACK clears up to @@ -725,7 +725,7 @@ if (!(flag & FLAG_DATA_ACKED)) return; - seq_rtt = jiffies-tp->rcv_tsecr; + seq_rtt = tcp_time_stamp - tp->rcv_tsecr; tcp_rtt_estimator(tp, seq_rtt); if (tp->retransmits) { if (tp->packets_out == 0) { @@ -749,7 +749,7 @@ static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp) { struct sk_buff *skb = skb_peek(&sk->write_queue); - long when = tp->rto - (jiffies - TCP_SKB_CB(skb)->when); + __u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when); /* Some data was ACK'd, if still retransmitting (due to a * timeout), resend more of the retransmit queue. The @@ -778,7 +778,7 @@ if (tp->pending == TIME_KEEPOPEN) tp->probes_out = 0; - tp->rcv_tstamp = jiffies; + tp->rcv_tstamp = tcp_time_stamp; /* If the ack is newer than sent or older than previous acks * then we can probably ignore it. @@ -2112,7 +2112,7 @@ tp->tcp_header_len = sizeof(struct tcphdr); if (tp->saw_tstamp) { tp->ts_recent = tp->rcv_tsval; - tp->ts_recent_stamp = jiffies; + tp->ts_recent_stamp = tcp_time_stamp; } /* Can't be earlier, doff would be wrong. */ @@ -2136,7 +2136,7 @@ tcp_parse_options(sk, th, tp, 0); if (tp->saw_tstamp) { tp->ts_recent = tp->rcv_tsval; - tp->ts_recent_stamp = jiffies; + tp->ts_recent_stamp = tcp_time_stamp; } tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; @@ -2189,8 +2189,22 @@ } } + /* The silly FIN test here is necessary to see an advancing ACK in + * retransmitted FIN frames properly. Consider the following sequence: + * + * host1 --> host2 FIN XSEQ:XSEQ(0) ack YSEQ + * host2 --> host1 FIN YSEQ:YSEQ(0) ack XSEQ + * host1 --> host2 XSEQ:XSEQ(0) ack YSEQ+1 + * host2 --> host1 FIN YSEQ:YSEQ(0) ack XSEQ+1 (fails tcp_sequence test) + * + * At this point the connection will deadlock with host1 believing + * that his FIN is never ACK'd, and thus it will retransmit it's FIN + * forever. The following fix is from Taral (taral@taral.net). + */ + /* step 1: check sequence number */ - if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { + if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq) && + !(th->fin && TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt)) { if (!th->rst) { tcp_send_ack(sk); goto discard; diff -u --recursive --new-file v2.2.6/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.2.6/linux/net/ipv4/tcp_ipv4.c Mon Mar 29 11:09:12 1999 +++ linux/net/ipv4/tcp_ipv4.c Wed Apr 28 09:51:57 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.171 1999/03/28 10:18:26 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.174 1999/04/28 16:08:19 davem Exp $ * * IPv4 specific functions * @@ -629,6 +629,7 @@ if (!tcp_v4_unique_address(sk)) { kfree_skb(buff); + sk->daddr = 0; return -EADDRNOTAVAIL; } @@ -722,7 +723,7 @@ /* * This routine does path mtu discovery as defined in RFC1191. */ -static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip) +static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip, unsigned mtu) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -742,8 +743,10 @@ * There is a small race when the user changes this flag in the * route, but I think that's acceptable. */ - if (sk->dst_cache && - sk->ip_pmtudisc != IP_PMTUDISC_DONT && + if (sk->dst_cache == NULL) + return; + ip_rt_update_pmtu(sk->dst_cache, mtu); + if (sk->ip_pmtudisc != IP_PMTUDISC_DONT && tp->pmtu_cookie > sk->dst_cache->pmtu) { tcp_sync_mss(sk, sk->dst_cache->pmtu); @@ -830,7 +833,7 @@ return; if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ - do_pmtu_discovery(sk, iph); + do_pmtu_discovery(sk, iph, ntohs(skb->h.icmph->un.frag.mtu)); return; } @@ -1355,7 +1358,14 @@ newtp->last_ack_sent = req->rcv_isn + 1; newtp->backoff = 0; newtp->mdev = TCP_TIMEOUT_INIT; - newtp->snd_cwnd = 1; + + /* So many TCP implementations out there (incorrectly) count the + * initial SYN frame in their delayed-ACK and congestion control + * algorithms that we must have the following bandaid to talk + * efficiently to them. -DaveM + */ + newtp->snd_cwnd = 2; + newtp->rto = TCP_TIMEOUT_INIT; newtp->packets_out = 0; newtp->fackets_out = 0; @@ -1420,7 +1430,7 @@ } if (newtp->tstamp_ok) { newtp->ts_recent = req->ts_recent; - newtp->ts_recent_stamp = jiffies; + newtp->ts_recent_stamp = tcp_time_stamp; newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED; } else { newtp->tcp_header_len = sizeof(struct tcphdr); @@ -1595,6 +1605,7 @@ * the new socket.. */ if (atomic_read(&nsk->sock_readers)) { + skb_orphan(skb); __skb_queue_tail(&nsk->back_log, skb); return 0; } @@ -1835,10 +1846,16 @@ tp->mdev = TCP_TIMEOUT_INIT; tp->mss_clamp = ~0; + /* So many TCP implementations out there (incorrectly) count the + * initial SYN frame in their delayed-ACK and congestion control + * algorithms that we must have the following bandaid to talk + * efficiently to them. -DaveM + */ + tp->snd_cwnd = 2; + /* See draft-stevens-tcpca-spec-01 for discussion of the * initialization of these values. */ - tp->snd_cwnd = 1; tp->snd_cwnd_cnt = 0; tp->snd_ssthresh = 0x7fffffff; /* Infinity */ diff -u --recursive --new-file v2.2.6/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.2.6/linux/net/ipv4/tcp_output.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/tcp_output.c Wed Apr 28 09:51:57 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.106 1999/03/12 03:43:51 davem Exp $ + * Version: $Id: tcp_output.c,v 1.107 1999/04/28 16:08:12 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -167,7 +167,7 @@ if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb)) { /* Send it out now. */ - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); @@ -344,7 +344,7 @@ /* Advance the send_head. This one is going out. */ update_send_head(sk); - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); @@ -600,7 +600,7 @@ /* Make a copy, if the first transmission SKB clone we made * is still in somebody's hands, else make a clone. */ - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; if(skb_cloned(skb)) skb = skb_copy(skb, GFP_ATOMIC); else @@ -723,7 +723,7 @@ tp->packets_out && !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) { update_send_head(sk); - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); @@ -778,7 +778,7 @@ /* Send it off. */ TCP_SKB_CB(skb)->seq = tp->write_seq; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq; - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tcp_transmit_skb(sk, skb); } @@ -808,7 +808,7 @@ TCP_SKB_CB(skb)->seq = tp->snd_una; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; __skb_queue_tail(&sk->write_queue, skb); - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); return 0; @@ -875,7 +875,7 @@ /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ th->window = htons(req->rcv_wnd); - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tcp_syn_build_options((__u32 *)(th + 1), req->mss, req->tstamp_ok, req->sack_ok, req->wscale_ok, req->rcv_wscale, TCP_SKB_CB(skb)->when, @@ -963,7 +963,7 @@ /* Send it off. */ __skb_queue_tail(&sk->write_queue, buff); - TCP_SKB_CB(buff)->when = jiffies; + TCP_SKB_CB(buff)->when = tcp_time_stamp; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL)); tcp_statistics.TcpActiveOpens++; @@ -1037,7 +1037,7 @@ /* Send it off, this clears delayed acks for us. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tp->snd_nxt; - TCP_SKB_CB(buff)->when = jiffies; + TCP_SKB_CB(buff)->when = tcp_time_stamp; tcp_transmit_skb(sk, buff); } } @@ -1075,7 +1075,7 @@ return; /* Let a retransmit get it. */ } update_send_head(sk); - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; tp->packets_out++; tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); @@ -1101,7 +1101,7 @@ */ TCP_SKB_CB(skb)->seq = tp->snd_nxt - 1; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq; - TCP_SKB_CB(skb)->when = jiffies; + TCP_SKB_CB(skb)->when = tcp_time_stamp; tcp_transmit_skb(sk, skb); } } diff -u --recursive --new-file v2.2.6/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c --- v2.2.6/linux/net/ipv4/tcp_timer.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/tcp_timer.c Wed Apr 28 09:51:57 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.59 1999/03/23 21:21:09 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.60 1999/04/28 16:08:21 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -224,7 +224,7 @@ if ((1<state) & (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT2)) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - __u32 elapsed = jiffies - tp->rcv_tstamp; + __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; if (elapsed >= sysctl_tcp_keepalive_time) { if (tp->probes_out > sysctl_tcp_keepalive_probes) { @@ -561,7 +561,7 @@ if (!tp->syn_wait_queue) break; } else { - __u32 timeo; + unsigned long timeo; struct open_request *op; (*conn->class->rtx_syn_ack)(sk, conn); diff -u --recursive --new-file v2.2.6/linux/net/ipv6/Makefile linux/net/ipv6/Makefile --- v2.2.6/linux/net/ipv6/Makefile Thu Mar 27 14:40:16 1997 +++ linux/net/ipv6/Makefile Thu Apr 22 19:45:20 1999 @@ -11,7 +11,8 @@ IPV6_OBJS := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ - exthdrs.o sysctl_net_ipv6.o datagram.o proc.o + exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ + ip6_flowlabel.o MOD_LIST_NAME := IPV6_MODULES M_OBJS := $(O_TARGET) diff -u --recursive --new-file v2.2.6/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- v2.2.6/linux/net/ipv6/af_inet6.c Wed Jan 20 23:14:07 1999 +++ linux/net/ipv6/af_inet6.c Thu Apr 22 19:45:20 1999 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.42 1999/01/19 08:20:06 davem Exp $ + * $Id: af_inet6.c,v 1.43 1999/04/22 10:07:39 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -190,7 +190,7 @@ struct sockaddr_in6 *addr=(struct sockaddr_in6 *)uaddr; struct sock *sk = sock->sk; __u32 v4addr = 0; - unsigned short snum = 0; + unsigned short snum; int addr_type = 0; /* If the socket has its own bind function then use it. */ @@ -203,12 +203,6 @@ (sk->num != 0)) return -EINVAL; - snum = ntohs(addr->sin6_port); - if (snum == 0) - snum = sk->prot->good_socknum(); - if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) - return(-EACCES); - addr_type = ipv6_addr_type(&addr->sin6_addr); if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) return(-EINVAL); @@ -241,6 +235,12 @@ memcpy(&sk->net_pinfo.af_inet6.saddr, &addr->sin6_addr, sizeof(struct in6_addr)); + snum = ntohs(addr->sin6_port); + if (snum == 0) + snum = sk->prot->good_socknum(); + if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return(-EACCES); + /* Make sure we are allowed to bind here. */ if(sk->prot->verify_bind(sk, snum)) return -EADDRINUSE; @@ -292,6 +292,9 @@ if ((skb = xchg(&sk->net_pinfo.af_inet6.pktoptions, NULL)) != NULL) kfree_skb(skb); + /* Free flowlabels */ + fl6_free_socklist(sk); + /* Free tx options */ if ((opt = xchg(&sk->net_pinfo.af_inet6.opt, NULL)) != NULL) @@ -311,6 +314,7 @@ struct sock *sk; sin->sin6_family = AF_INET6; + sin->sin6_flowinfo = 0; sk = sock->sk; if (peer) { if (!tcp_connected(sk->state)) @@ -318,6 +322,8 @@ sin->sin6_port = sk->dport; memcpy(&sin->sin6_addr, &sk->net_pinfo.af_inet6.daddr, sizeof(struct in6_addr)); + if (sk->net_pinfo.af_inet6.sndflow) + sin->sin6_flowinfo = sk->net_pinfo.af_inet6.flow_label; } else { if (ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr) == IPV6_ADDR_ANY) memcpy(&sin->sin6_addr, @@ -537,6 +543,7 @@ ipv6_netdev_notif_init(); ipv6_packet_init(); ip6_route_init(); + ip6_flowlabel_init(); addrconf_init(); sit_init(); @@ -592,6 +599,7 @@ /* Cleanup code parts. */ sit_cleanup(); ipv6_netdev_notif_cleanup(); + ip6_flowlabel_cleanup(); addrconf_cleanup(); ip6_route_cleanup(); ipv6_packet_cleanup(); diff -u --recursive --new-file v2.2.6/linux/net/ipv6/datagram.c linux/net/ipv6/datagram.c --- v2.2.6/linux/net/ipv6/datagram.c Mon Oct 5 13:13:49 1998 +++ linux/net/ipv6/datagram.c Thu Apr 22 19:45:20 1999 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: datagram.c,v 1.16 1998/10/03 09:38:25 davem Exp $ + * $Id: datagram.c,v 1.17 1999/04/22 10:07:40 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -132,10 +132,13 @@ sin = (struct sockaddr_in6 *)msg->msg_name; if (sin) { sin->sin6_family = AF_INET6; + sin->sin6_flowinfo = 0; sin->sin6_port = serr->port; - if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) + if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { memcpy(&sin->sin6_addr, skb->nh.raw + serr->addr_offset, 16); - else + if (sk->net_pinfo.af_inet6.sndflow) + sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; + } else ipv6_addr_set(&sin->sin6_addr, 0, 0, __constant_htonl(0xffff), *(u32*)(skb->nh.raw + serr->addr_offset)); @@ -146,6 +149,7 @@ sin->sin6_family = AF_UNSPEC; if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { sin->sin6_family = AF_INET6; + sin->sin6_flowinfo = 0; if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr, 16); if (sk->net_pinfo.af_inet6.rxopt.all) @@ -199,6 +203,10 @@ put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); } + if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { + u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK; + put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); + } if (np->rxopt.bits.hopopts && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); @@ -222,8 +230,8 @@ return 0; } -int datagram_send_ctl(struct msghdr *msg, int *oif, - struct in6_addr **src_addr, struct ipv6_txoptions *opt, +int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, + struct ipv6_txoptions *opt, int *hlimit) { struct in6_pktinfo *src_info; @@ -235,17 +243,15 @@ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { - if ((unsigned long)(((char*)cmsg - (char*)msg->msg_control) + if (cmsg->cmsg_len < sizeof(struct cmsghdr) || + (unsigned long)(((char*)cmsg - (char*)msg->msg_control) + cmsg->cmsg_len) > msg->msg_controllen) { err = -EINVAL; goto exit_f; } - if (cmsg->cmsg_level != SOL_IPV6) { - if (net_ratelimit()) - printk(KERN_DEBUG "invalid cmsg_level %d\n", cmsg->cmsg_level); + if (cmsg->cmsg_level != SOL_IPV6) continue; - } switch (cmsg->cmsg_type) { case IPV6_PKTINFO: @@ -257,9 +263,9 @@ src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); if (src_info->ipi6_ifindex) { - if (*oif && src_info->ipi6_ifindex != *oif) + if (fl->oif && src_info->ipi6_ifindex != fl->oif) return -EINVAL; - *oif = src_info->ipi6_ifindex; + fl->oif = src_info->ipi6_ifindex; } if (!ipv6_addr_any(&src_info->ipi6_addr)) { @@ -272,9 +278,24 @@ goto exit_f; } - *src_addr = &src_info->ipi6_addr; + fl->fl6_src = &src_info->ipi6_addr; + } + + break; + + case IPV6_FLOWINFO: + if (cmsg->cmsg_len < CMSG_LEN(4)) { + err = -EINVAL; + goto exit_f; } + if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) { + if ((fl->fl6_flowlabel^*(u32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { + err = -EINVAL; + goto exit_f; + } + } + fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); break; case IPV6_HOPOPTS: diff -u --recursive --new-file v2.2.6/linux/net/ipv6/ip6_fib.c linux/net/ipv6/ip6_fib.c --- v2.2.6/linux/net/ipv6/ip6_fib.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv6/ip6_fib.c Thu Apr 22 19:45:20 1999 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_fib.c,v 1.16 1999/03/21 05:22:52 davem Exp $ + * $Id: ip6_fib.c,v 1.17 1999/04/22 10:07:41 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -890,9 +890,6 @@ RT6_TRACE("fib6_del_route\n"); - if (!(rt->rt6i_flags&RTF_CACHE)) - fib6_prune_clones(fn, rt); - /* Unlink it */ *rtp = rt->u.next; rt->rt6i_node = NULL; @@ -938,6 +935,9 @@ return -ENOENT; BUG_TRAP(fn->fn_flags&RTN_RTINFO); + + if (!(rt->rt6i_flags&RTF_CACHE)) + fib6_prune_clones(fn, rt); /* * Walk the leaf entries looking for ourself diff -u --recursive --new-file v2.2.6/linux/net/ipv6/ip6_flowlabel.c linux/net/ipv6/ip6_flowlabel.c --- v2.2.6/linux/net/ipv6/ip6_flowlabel.c Wed Dec 31 16:00:00 1969 +++ linux/net/ipv6/ip6_flowlabel.c Fri Apr 23 18:39:47 1999 @@ -0,0 +1,620 @@ +/* + * ip6_flowlabel.c IPv6 flowlabel manager. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Alexey Kuznetsov, + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FL_MIN_LINGER 6 /* Minimal linger. It is set to 6sec specified + in old IPv6 RFC. Well, it was reasonable value. + */ +#define FL_MAX_LINGER 60 /* Maximal linger timeout */ + +/* FL hash table */ + +#define FL_MAX_PER_SOCK 32 +#define FL_MAX_SIZE 4096 +#define FL_HASH_MASK 255 +#define FL_HASH(l) (ntohl(l)&FL_HASH_MASK) + +static atomic_t fl_size = ATOMIC_INIT(0); +static struct ip6_flowlabel *fl_ht[FL_HASH_MASK+1]; + +static struct timer_list ip6_fl_gc_timer; + +/* FL hash table lock: it protects only of GC */ + +static atomic_t ip6_fl_lock = ATOMIC_INIT(0); + +static __inline__ void fl_lock(void) +{ + atomic_inc(&ip6_fl_lock); + synchronize_bh(); +} + +static __inline__ void fl_unlock(void) +{ + atomic_dec(&ip6_fl_lock); +} + +static struct ip6_flowlabel * fl_lookup(u32 label) +{ + struct ip6_flowlabel *fl; + + fl_lock(); + for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) { + if (fl->label == label) { + atomic_inc(&fl->users); + break; + } + } + fl_unlock(); + return fl; +} + +static void fl_free(struct ip6_flowlabel *fl) +{ + if (fl->opt) + kfree(fl->opt); + kfree(fl); +} + +static void fl_release(struct ip6_flowlabel *fl) +{ + fl_lock(); + fl->lastuse = jiffies; + if (atomic_dec_and_test(&fl->users)) { + unsigned long ttd = fl->lastuse + fl->linger; + if ((long)(ttd - fl->expires) > 0) + fl->expires = ttd; + ttd = fl->expires; + if (fl->opt && fl->share == IPV6_FL_S_EXCL) { + struct ipv6_txoptions *opt = fl->opt; + fl->opt = NULL; + kfree(opt); + } + if (!del_timer(&ip6_fl_gc_timer) || + (long)(ip6_fl_gc_timer.expires - ttd) > 0) + ip6_fl_gc_timer.expires = ttd; + add_timer(&ip6_fl_gc_timer); + } + fl_unlock(); +} + +static void ip6_fl_gc(unsigned long dummy) +{ + int i; + unsigned long now = jiffies; + unsigned long sched = 0; + + if (atomic_read(&ip6_fl_lock)) { + ip6_fl_gc_timer.expires = now + HZ/10; + add_timer(&ip6_fl_gc_timer); + return; + } + + for (i=0; i<=FL_HASH_MASK; i++) { + struct ip6_flowlabel *fl, **flp; + flp = &fl_ht[i]; + while ((fl=*flp) != NULL) { + if (atomic_read(&fl->users) == 0) { + unsigned long ttd = fl->lastuse + fl->linger; + if ((long)(ttd - fl->expires) > 0) + fl->expires = ttd; + ttd = fl->expires; + if ((long)(now - ttd) >= 0) { + *flp = fl->next; + fl_free(fl); + atomic_dec(&fl_size); + continue; + } + if (!sched || (long)(ttd - sched) < 0) + sched = ttd; + } + flp = &fl->next; + } + } + if (!sched && atomic_read(&fl_size)) + sched = now + FL_MAX_LINGER; + if (sched) { + ip6_fl_gc_timer.expires = sched; + add_timer(&ip6_fl_gc_timer); + } +} + +static int fl_intern(struct ip6_flowlabel *fl, __u32 label) +{ + fl->label = label & IPV6_FLOWLABEL_MASK; + + fl_lock(); + if (label == 0) { + for (;;) { + fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; + if (fl->label) { + struct ip6_flowlabel *lfl; + lfl = fl_lookup(fl->label); + if (lfl == NULL) + break; + fl_release(lfl); + } + } + } + + fl->lastuse = jiffies; + fl->next = fl_ht[FL_HASH(fl->label)]; + fl_ht[FL_HASH(fl->label)] = fl; + atomic_inc(&fl_size); + fl_unlock(); + return 0; +} + + + +/* Socket flowlabel lists */ + +struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label) +{ + struct ipv6_fl_socklist *sfl; + struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + + label &= IPV6_FLOWLABEL_MASK; + + for (sfl=np->ipv6_fl_list; sfl; sfl = sfl->next) { + struct ip6_flowlabel *fl = sfl->fl; + if (fl->label == label) { + fl->lastuse = jiffies; + atomic_inc(&fl->users); + return fl; + } + } + return NULL; +} + +void fl6_free_socklist(struct sock *sk) +{ + struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_fl_socklist *sfl; + + while ((sfl = np->ipv6_fl_list) != NULL) { + np->ipv6_fl_list = sfl->next; + fl_release(sfl->fl); + kfree(sfl); + } +} + +/* Service routines */ + + +/* + It is the only difficult place. flowlabel enforces equal headers + before and including routing header, however user may supply options + following rthdr. + */ + +struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, + struct ip6_flowlabel * fl, + struct ipv6_txoptions * fopt) +{ + struct ipv6_txoptions * fl_opt = fl->opt; + + if (fopt == NULL || fopt->opt_flen == 0) + return fl_opt; + + if (fl_opt != NULL) { + opt_space->hopopt = fl_opt->hopopt; + opt_space->dst0opt = fl_opt->dst0opt; + opt_space->srcrt = fl_opt->srcrt; + opt_space->opt_nflen = fl_opt->opt_nflen; + } else { + if (fopt->opt_nflen == 0) + return fopt; + opt_space->hopopt = NULL; + opt_space->dst0opt = NULL; + opt_space->srcrt = NULL; + opt_space->opt_nflen = 0; + } + opt_space->dst1opt = fopt->dst1opt; + opt_space->auth = fopt->auth; + opt_space->opt_flen = fopt->opt_flen; + return opt_space; +} + +static __u32 check_linger(__u16 ttl) +{ + if (ttl < FL_MIN_LINGER) + return FL_MIN_LINGER*HZ; + if (ttl > FL_MAX_LINGER && !capable(CAP_NET_ADMIN)) + return 0; + return ttl*HZ; +} + +static int fl6_renew(struct ip6_flowlabel *fl, unsigned linger, unsigned expires) +{ + linger = check_linger(linger); + if (!linger) + return -EPERM; + expires = check_linger(expires); + if (!expires) + return -EPERM; + fl->lastuse = jiffies; + if (fl->linger < linger) + fl->linger = linger; + if (expires < fl->linger) + expires = fl->linger; + if ((long)(fl->expires - (fl->lastuse+expires)) < 0) + fl->expires = fl->lastuse + expires; + return 0; +} + +static struct ip6_flowlabel * +fl_create(struct in6_flowlabel_req *freq, char *optval, int optlen, int *err_p) +{ + struct ip6_flowlabel *fl; + int olen; + int addr_type; + int err; + + err = -ENOMEM; + fl = kmalloc(sizeof(*fl), GFP_KERNEL); + if (fl == NULL) + goto done; + memset(fl, 0, sizeof(*fl)); + + olen = optlen - CMSG_ALIGN(sizeof(*freq)); + if (olen > 0) { + struct msghdr msg; + struct flowi flowi; + int junk; + + err = -ENOMEM; + fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL); + if (fl->opt == NULL) + goto done; + + memset(fl->opt, 0, sizeof(*fl->opt)); + fl->opt->tot_len = sizeof(*fl->opt) + olen; + err = -EFAULT; + if (copy_from_user(fl->opt+1, optval+CMSG_ALIGN(sizeof(*freq)), olen)) + goto done; + + msg.msg_controllen = olen; + msg.msg_control = (void*)(fl->opt+1); + flowi.oif = 0; + + err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk); + if (err) + goto done; + err = -EINVAL; + if (fl->opt->opt_flen) + goto done; + if (fl->opt->opt_nflen == 0) { + kfree(fl->opt); + fl->opt = NULL; + } + } + + fl->expires = jiffies; + err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); + if (err) + goto done; + fl->share = freq->flr_share; + addr_type = ipv6_addr_type(&freq->flr_dst); + if ((addr_type&IPV6_ADDR_MAPPED) + || addr_type == IPV6_ADDR_ANY) + goto done; + ipv6_addr_copy(&fl->dst, &freq->flr_dst); + atomic_set(&fl->users, 1); + switch (fl->share) { + case IPV6_FL_S_EXCL: + case IPV6_FL_S_ANY: + break; + case IPV6_FL_S_PROCESS: + fl->owner = current->pid; + break; + case IPV6_FL_S_USER: + fl->owner = current->euid; + break; + default: + err = -EINVAL; + goto done; + } + return fl; + +done: + if (fl) + fl_free(fl); + *err_p = err; + return NULL; +} + +static int mem_check(struct sock *sk) +{ + struct ipv6_fl_socklist *sfl; + int room = FL_MAX_SIZE - atomic_read(&fl_size); + int count = 0; + + if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) + return 0; + + for (sfl = sk->net_pinfo.af_inet6.ipv6_fl_list; sfl; sfl = sfl->next) + count++; + + if (room <= 0 || + ((count >= FL_MAX_PER_SOCK || + (count > 0 && room < FL_MAX_SIZE/2) || room < FL_MAX_SIZE/4) + && !capable(CAP_NET_ADMIN))) + return -ENOBUFS; + + return 0; +} + +static int ipv6_hdr_cmp(struct ipv6_opt_hdr *h1, struct ipv6_opt_hdr *h2) +{ + if (h1 == h2) + return 0; + if (h1 == NULL || h2 == NULL) + return 1; + if (h1->hdrlen != h2->hdrlen) + return 1; + return memcmp(h1+1, h2+1, ((h1->hdrlen+1)<<3) - sizeof(*h1)); +} + +static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2) +{ + if (o1 == o2) + return 0; + if (o1 == NULL || o2 == NULL) + return 1; + if (o1->opt_nflen != o2->opt_nflen) + return 1; + if (ipv6_hdr_cmp(o1->hopopt, o2->hopopt)) + return 1; + if (ipv6_hdr_cmp(o1->dst0opt, o2->dst0opt)) + return 1; + if (ipv6_hdr_cmp((struct ipv6_opt_hdr *)o1->srcrt, (struct ipv6_opt_hdr *)o2->srcrt)) + return 1; + return 0; +} + +int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen) +{ + int err; + struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct in6_flowlabel_req freq; + struct ipv6_fl_socklist *sfl1=NULL; + struct ipv6_fl_socklist *sfl, **sflp; + struct ip6_flowlabel *fl; + + if (optlen < sizeof(freq)) + return -EINVAL; + + if (copy_from_user(&freq, optval, sizeof(freq))) + return -EFAULT; + + switch (freq.flr_action) { + case IPV6_FL_A_PUT: + for (sflp = &np->ipv6_fl_list; (sfl=*sflp)!=NULL; sflp = &sfl->next) { + if (sfl->fl->label == freq.flr_label) { + if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK)) + np->flow_label &= ~IPV6_FLOWLABEL_MASK; + *sflp = sfl->next; + synchronize_bh(); + fl_release(sfl->fl); + kfree(sfl); + return 0; + } + } + return -ESRCH; + + case IPV6_FL_A_RENEW: + for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { + if (sfl->fl->label == freq.flr_label) + return fl6_renew(sfl->fl, freq.flr_linger, freq.flr_expires); + } + if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { + fl = fl_lookup(freq.flr_label); + if (fl) { + err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); + fl_release(fl); + return err; + } + } + return -ESRCH; + + case IPV6_FL_A_GET: + if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) + return -EINVAL; + + fl = fl_create(&freq, optval, optlen, &err); + if (fl == NULL) + return err; + sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); + + if (freq.flr_label) { + struct ip6_flowlabel *fl1 = NULL; + + err = -EEXIST; + for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { + if (sfl->fl->label == freq.flr_label) { + if (freq.flr_flags&IPV6_FL_F_EXCL) + goto done; + fl1 = sfl->fl; + atomic_inc(&fl->users); + break; + } + } + + if (fl1 == NULL) + fl1 = fl_lookup(freq.flr_label); + if (fl1) { + err = -EEXIST; + if (freq.flr_flags&IPV6_FL_F_EXCL) + goto release; + err = -EPERM; + if (fl1->share == IPV6_FL_S_EXCL || + fl1->share != fl->share || + fl1->owner != fl->owner) + goto release; + + err = -EINVAL; + if (ipv6_addr_cmp(&fl1->dst, &fl->dst) || + ipv6_opt_cmp(fl1->opt, fl->opt)) + goto release; + + err = -ENOMEM; + if (sfl1 == NULL) + goto release; + if (fl->linger > fl1->linger) + fl1->linger = fl->linger; + if ((long)(fl->expires - fl1->expires) > 0) + fl1->expires = fl->expires; + sfl1->fl = fl1; + sfl1->next = np->ipv6_fl_list; + np->ipv6_fl_list = sfl1; + synchronize_bh(); + fl_free(fl); + return 0; + +release: + fl_release(fl1); + goto done; + } + } + err = -ENOENT; + if (!(freq.flr_flags&IPV6_FL_F_CREATE)) + goto done; + + err = -ENOMEM; + if (sfl1 == NULL || (err = mem_check(sk)) != 0) + goto done; + + err = fl_intern(fl, freq.flr_label); + if (err) + goto done; + + /* Do not check for fault */ + if (!freq.flr_label) + copy_to_user(optval + ((u8*)&freq.flr_label - (u8*)&freq), &fl->label, sizeof(fl->label)); + + sfl1->fl = fl; + sfl1->next = np->ipv6_fl_list; + np->ipv6_fl_list = sfl1; + return 0; + + default: + return -EINVAL; + } + +done: + if (fl) + fl_free(fl); + if (sfl1) + kfree(sfl1); + return err; +} + +#ifdef CONFIG_PROC_FS + + +static int ip6_fl_read_proc(char *buffer, char **start, off_t offset, + int length, int *eof, void *data) +{ + off_t pos=0; + off_t begin=0; + int len=0; + int i, k; + struct ip6_flowlabel *fl; + + len+= sprintf(buffer,"Label S Owner Users Linger Expires " + "Dst Opt\n"); + + fl_lock(); + for (i=0; i<=FL_HASH_MASK; i++) { + for (fl = fl_ht[i]; fl; fl = fl->next) { + len+=sprintf(buffer+len,"%05X %-1d %-6d %-6d %-6d %-8ld ", + (unsigned)ntohl(fl->label), + fl->share, + (unsigned)fl->owner, + atomic_read(&fl->users), + fl->linger/HZ, + (long)(fl->expires - jiffies)/HZ); + + for (k=0; k<16; k++) + len+=sprintf(buffer+len, "%02x", fl->dst.s6_addr[k]); + buffer[len++]=' '; + len+=sprintf(buffer+len, "%-4d", fl->opt ? fl->opt->opt_nflen : 0); + buffer[len++]='\n'; + + pos=begin+len; + if(posoffset+length) + goto done; + } + } + *eof = 1; + +done: + fl_unlock(); + *start=buffer+(offset-begin); + len-=(offset-begin); + if(len>length) + len=length; + if(len<0) + len=0; + return len; +} +#endif + + +void ip6_flowlabel_init() +{ +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + + init_timer(&ip6_fl_gc_timer); + ip6_fl_gc_timer.function = ip6_fl_gc; +#ifdef CONFIG_PROC_FS + ent = create_proc_entry("net/ip6_flowlabel", 0, 0); + ent->read_proc = ip6_fl_read_proc; +#endif +} + +void ip6_flowlabel_cleanup() +{ + del_timer(&ip6_fl_gc_timer); +#ifdef CONFIG_PROC_FS + remove_proc_entry("net/ip6_flowlabel", 0); +#endif +} diff -u --recursive --new-file v2.2.6/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c --- v2.2.6/linux/net/ipv6/ip6_output.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv6/ip6_output.c Thu Apr 22 19:45:20 1999 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_output.c,v 1.16 1999/03/21 05:22:54 davem Exp $ + * $Id: ip6_output.c,v 1.17 1999/04/22 10:07:42 davem Exp $ * * Based on linux/net/ipv4/ip_output.c * @@ -140,16 +140,10 @@ * Fill in the IPv6 header */ - hdr->version = 6; - if (np) { - hdr->priority = np->priority; - memcpy(hdr->flow_lbl, (void *) &np->flow_lbl, 3); + *(u32*)hdr = __constant_htonl(0x60000000) | fl->fl6_flowlabel; + hlimit = -1; + if (np) hlimit = np->hop_limit; - } else { - hdr->priority = 0; - memset(hdr->flow_lbl, 0, 3); - hlimit = -1; - } if (hlimit < 0) hlimit = ((struct rt6_info*)dst)->rt6i_hoplimit; @@ -197,9 +191,7 @@ hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); skb->nh.ipv6h = hdr; - hdr->version = 6; - hdr->priority = np->priority & 0x0f; - memset(hdr->flow_lbl, 0, 3); + *(u32*)hdr = htonl(0x60000000); hdr->payload_len = htons(len); hdr->nexthdr = proto; @@ -214,16 +206,13 @@ static struct ipv6hdr * ip6_bld_1(struct sock *sk, struct sk_buff *skb, struct flowi *fl, int hlimit, unsigned pktlength) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6hdr *hdr; skb->nh.raw = skb_put(skb, sizeof(struct ipv6hdr)); hdr = skb->nh.ipv6h; - hdr->version = 6; - hdr->priority = np->priority; - memcpy(hdr->flow_lbl, &np->flow_lbl, 3); - + *(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000); + hdr->payload_len = htons(pktlength - sizeof(struct ipv6hdr)); hdr->hop_limit = hlimit; hdr->nexthdr = fl->proto; @@ -436,8 +425,8 @@ if (opt && opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; - final_dst = fl->nl_u.ip6_u.daddr; - fl->nl_u.ip6_u.daddr = rt0->addr; + final_dst = fl->fl6_dst; + fl->fl6_dst = rt0->addr; } if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr)) @@ -486,8 +475,8 @@ return -ENETUNREACH; } - if (fl->nl_u.ip6_u.saddr == NULL) { - err = ipv6_get_saddr(dst, fl->nl_u.ip6_u.daddr, &saddr); + if (fl->fl6_src == NULL) { + err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr); if (err) { #if IP6_DEBUG >= 2 @@ -496,12 +485,12 @@ #endif goto out; } - fl->nl_u.ip6_u.saddr = &saddr; + fl->fl6_src = &saddr; } pktlength = length; if (hlimit < 0) { - if (ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr)) + if (ipv6_addr_is_multicast(fl->fl6_dst)) hlimit = np->mcast_hops; else hlimit = np->hop_limit; diff -u --recursive --new-file v2.2.6/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c --- v2.2.6/linux/net/ipv6/ipv6_sockglue.c Mon Mar 29 11:09:12 1999 +++ linux/net/ipv6/ipv6_sockglue.c Thu Apr 22 19:45:20 1999 @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.26 1999/03/25 10:04:53 davem Exp $ + * $Id: ipv6_sockglue.c,v 1.27 1999/04/22 10:07:43 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -151,6 +151,9 @@ goto addrform_done; } + fl6_free_socklist(sk); + ipv6_sock_mc_close(sk); + if (sk->protocol == IPPROTO_TCP) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); @@ -211,12 +214,19 @@ retv = 0; break; + case IPV6_FLOWINFO: + np->rxopt.bits.rxflow = valbool; + return 0; + case IPV6_PKTOPTIONS: { struct ipv6_txoptions *opt = NULL; struct msghdr msg; + struct flowi fl; int junk; - struct in6_addr *saddr; + + fl.fl6_flowlabel = 0; + fl.oif = sk->bound_dev_if; if (optlen == 0) goto update; @@ -235,7 +245,7 @@ msg.msg_controllen = optlen; msg.msg_control = (void*)(opt+1); - retv = datagram_send_ctl(&msg, &junk, &saddr, opt, &junk); + retv = datagram_send_ctl(&msg, &fl, opt, &junk); if (retv) goto done; update: @@ -321,10 +331,15 @@ np->frag_size = val; return 0; case IPV6_RECVERR: - np->recverr = !!val; + np->recverr = valbool; if (!val) skb_queue_purge(&sk->error_queue); return 0; + case IPV6_FLOWINFO_SEND: + np->sndflow = valbool; + return 0; + case IPV6_FLOWLABEL_MGR: + return ipv6_flowlabel_opt(sk, optval, optlen); }; out: diff -u --recursive --new-file v2.2.6/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c --- v2.2.6/linux/net/ipv6/ndisc.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv6/ndisc.c Thu Apr 22 19:45:20 1999 @@ -813,7 +813,7 @@ } } - rd_len = min(IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, ntohs(skb->nh.ipv6h->payload_len) + 8); + rd_len = min(IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8); rd_len &= ~0x7; len += rd_len; @@ -873,7 +873,7 @@ *(opt++) = (rd_len >> 3); opt += 6; - memcpy(opt, &skb->nh.ipv6h, rd_len - 8); + memcpy(opt, skb->nh.ipv6h, rd_len - 8); icmph->icmp6_cksum = csum_ipv6_magic(&ifp->addr, &skb->nh.ipv6h->saddr, len, IPPROTO_ICMPV6, diff -u --recursive --new-file v2.2.6/linux/net/ipv6/raw.c linux/net/ipv6/raw.c --- v2.2.6/linux/net/ipv6/raw.c Thu Nov 19 09:56:29 1998 +++ linux/net/ipv6/raw.c Thu Apr 22 19:45:20 1999 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw.c,v 1.23 1998/11/08 11:17:09 davem Exp $ + * $Id: raw.c,v 1.24 1999/04/22 10:07:45 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -283,6 +283,7 @@ sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr)); + sin6->sin6_flowinfo = 0; } if (sk->net_pinfo.af_inet6.rxopt.all) @@ -363,7 +364,7 @@ struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_txoptions *opt = NULL; - struct in6_addr *saddr = NULL; + struct ip6_flowlabel *flowlabel = NULL; struct flowi fl; int addr_len = msg->msg_namelen; struct in6_addr *daddr; @@ -388,6 +389,8 @@ * Get and verify the address. */ + fl.fl6_flowlabel = 0; + if (sin6) { if (addr_len < sizeof(struct sockaddr_in6)) return(-EINVAL); @@ -405,12 +408,28 @@ return(-EINVAL); daddr = &sin6->sin6_addr; + if (np->sndflow) { + fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; + if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + daddr = &flowlabel->dst; + } + } + + + /* Otherwise it will be difficult to maintain sk->dst_cache. */ + if (sk->state == TCP_ESTABLISHED && + !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr)) + daddr = &sk->net_pinfo.af_inet6.daddr; } else { if (sk->state != TCP_ESTABLISHED) return(-EINVAL); proto = sk->num; daddr = &(sk->net_pinfo.af_inet6.daddr); + fl.fl6_flowlabel = np->flow_label; } if (ipv6_addr_any(daddr)) { @@ -422,23 +441,34 @@ } fl.oif = sk->bound_dev_if; + fl.fl6_src = NULL; if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); - err = datagram_send_ctl(msg, &fl.oif, &saddr, opt, &hlimit); - if (err < 0) + err = datagram_send_ctl(msg, &fl, opt, &hlimit); + if (err < 0) { + fl6_sock_release(flowlabel); return err; + } + if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + } + if (!(opt->opt_nflen|opt->opt_flen)) + opt = NULL; } - if (opt == NULL || !(opt->opt_nflen|opt->opt_flen)) + if (opt == NULL) opt = np->opt; + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); raw_opt = &sk->tp_pinfo.tp_raw; fl.proto = proto; - fl.nl_u.ip6_u.daddr = daddr; - fl.nl_u.ip6_u.saddr = saddr; + fl.fl6_dst = daddr; fl.uli_u.icmpt.type = 0; fl.uli_u.icmpt.code = 0; @@ -462,6 +492,8 @@ err = ip6_build_xmit(sk, rawv6_getfrag, msg->msg_iov, &fl, len, opt, hlimit, msg->msg_flags); } + + fl6_sock_release(flowlabel); return err<0?err:len; } diff -u --recursive --new-file v2.2.6/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.2.6/linux/net/ipv6/tcp_ipv6.c Fri Apr 16 14:47:31 1999 +++ linux/net/ipv6/tcp_ipv6.c Fri Apr 23 18:39:47 1999 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.101 1999/03/28 10:18:30 davem Exp $ + * $Id: tcp_ipv6.c,v 1.104 1999/04/24 00:27:25 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -401,6 +401,19 @@ if (usin->sin6_family && usin->sin6_family != AF_INET6) return(-EAFNOSUPPORT); + fl.fl6_flowlabel = 0; + if (np->sndflow) { + fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; + if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { + struct ip6_flowlabel *flowlabel; + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); + fl6_sock_release(flowlabel); + } + } + /* * connect() to INADDR_ANY means loopback (BSD'ism). */ @@ -422,6 +435,7 @@ return (-EINVAL); memcpy(&np->daddr, &usin->sin6_addr, sizeof(struct in6_addr)); + np->flow_label = fl.fl6_flowlabel; /* * TCP over IPv4 @@ -446,6 +460,7 @@ tp->ext_header_len = exthdrlen; sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific; sk->backlog_rcv = tcp_v6_do_rcv; + goto failure; } else { ipv6_addr_set(&np->saddr, 0, 0, __constant_htonl(0x0000FFFF), sk->saddr); @@ -460,8 +475,8 @@ saddr = &np->rcv_saddr; fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = saddr; + fl.fl6_dst = &np->daddr; + fl.fl6_src = saddr; fl.oif = sk->bound_dev_if; fl.uli_u.ports.dport = usin->sin6_port; fl.uli_u.ports.sport = sk->sport; @@ -475,7 +490,7 @@ if ((err = dst->error) != 0) { dst_release(dst); - return err; + goto failure; } if (fl.oif == 0 && addr_type&IPV6_ADDR_LINKLOCAL) { @@ -492,7 +507,7 @@ if (saddr == NULL) { err = ipv6_get_saddr(dst, &np->daddr, &saddr_buf); if (err) - return err; + goto failure; saddr = &saddr_buf; } @@ -507,17 +522,19 @@ /* Reset mss clamp */ tp->mss_clamp = ~0; + err = -ENOBUFS; buff = sock_wmalloc(sk, (MAX_HEADER + sk->prot->max_header), 0, GFP_KERNEL); if (buff == NULL) - return -ENOBUFS; + goto failure; sk->dport = usin->sin6_port; if (!tcp_v6_unique_address(sk)) { kfree_skb(buff); - return -EADDRNOTAVAIL; + err = -EADDRNOTAVAIL; + goto failure; } /* @@ -531,6 +548,12 @@ tcp_connect(sk, buff, dst->pmtu); return 0; + +failure: + dst_release(xchg(&sk->dst_cache, NULL)); + memcpy(&np->daddr, 0, sizeof(struct in6_addr)); + sk->daddr = 0; + return err; } static int tcp_v6_sendmsg(struct sock *sk, struct msghdr *msg, int len) @@ -561,6 +584,8 @@ goto out; if (ipv6_addr_cmp(&addr->sin6_addr, &np->daddr)) goto out; + if (np->sndflow && np->flow_label != (addr->sin6_flowinfo&IPV6_FLOWINFO_MASK)) + goto out; } retval = tcp_do_sendmsg(sk, msg); @@ -712,6 +737,7 @@ fl.proto = IPPROTO_TCP; fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr; fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr; + fl.fl6_flowlabel = 0; fl.oif = req->af.v6_req.iif; fl.uli_u.ports.dport = req->rmt_port; fl.uli_u.ports.sport = sk->sport; @@ -775,6 +801,8 @@ if (sk->net_pinfo.af_inet6.rxopt.all) { if ((opt->hop && sk->net_pinfo.af_inet6.rxopt.bits.hopopts) || + ((IPV6_FLOWINFO_MASK&*(u32*)skb->nh.raw) && + sk->net_pinfo.af_inet6.rxopt.bits.rxflow) || (opt->srcrt && sk->net_pinfo.af_inet6.rxopt.bits.srcrt) || ((opt->dst1 || opt->dst0) && sk->net_pinfo.af_inet6.rxopt.bits.dstopts)) return 1; @@ -953,6 +981,7 @@ fl.nl_u.ip6_u.daddr = rt0->addr; } fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr; + fl.fl6_flowlabel = 0; fl.oif = sk->bound_dev_if; fl.uli_u.ports.dport = req->rmt_port; fl.uli_u.ports.sport = sk->sport; @@ -1078,6 +1107,7 @@ fl.nl_u.ip6_u.daddr = &skb->nh.ipv6h->saddr; fl.nl_u.ip6_u.saddr = &skb->nh.ipv6h->daddr; + fl.fl6_flowlabel = 0; t1->check = csum_ipv6_magic(fl.nl_u.ip6_u.saddr, fl.nl_u.ip6_u.daddr, @@ -1257,6 +1287,7 @@ * the new socket.. */ if (atomic_read(&nsk->sock_readers)) { + skb_orphan(skb); __skb_queue_tail(&nsk->back_log, skb); return 0; } @@ -1404,6 +1435,7 @@ fl.proto = IPPROTO_TCP; fl.nl_u.ip6_u.daddr = &np->daddr; fl.nl_u.ip6_u.saddr = &np->saddr; + fl.fl6_flowlabel = np->flow_label; fl.oif = sk->bound_dev_if; fl.uli_u.ports.dport = sk->dport; fl.uli_u.ports.sport = sk->sport; @@ -1448,8 +1480,9 @@ struct dst_entry *dst = sk->dst_cache; fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = &np->saddr; + fl.fl6_dst = &np->daddr; + fl.fl6_src = &np->saddr; + fl.fl6_flowlabel = np->flow_label; fl.oif = sk->bound_dev_if; fl.uli_u.ports.sport = sk->sport; fl.uli_u.ports.dport = sk->dport; @@ -1490,6 +1523,8 @@ sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, &np->daddr, sizeof(struct in6_addr)); sin6->sin6_port = sk->dport; + /* We do not store received flowlabel for TCP */ + sin6->sin6_flowinfo = 0; } static struct tcp_func ipv6_specific = { @@ -1540,10 +1575,16 @@ tp->mdev = TCP_TIMEOUT_INIT; tp->mss_clamp = ~0; + /* So many TCP implementations out there (incorrectly) count the + * initial SYN frame in their delayed-ACK and congestion control + * algorithms that we must have the following bandaid to talk + * efficiently to them. -DaveM + */ + tp->snd_cwnd = 2; + /* See draft-stevens-tcpca-spec-01 for discussion of the * initialization of these values. */ - tp->snd_cwnd = 1; tp->snd_cwnd_cnt = 0; tp->snd_ssthresh = 0x7fffffff; diff -u --recursive --new-file v2.2.6/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.2.6/linux/net/ipv6/udp.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv6/udp.c Thu Apr 22 19:45:20 1999 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.38 1999/03/21 05:23:00 davem Exp $ + * $Id: udp.c,v 1.39 1999/04/22 10:07:47 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -204,6 +204,7 @@ struct in6_addr saddr; struct dst_entry *dst; struct flowi fl; + struct ip6_flowlabel *flowlabel = NULL; int addr_type; int err; @@ -218,6 +219,17 @@ if (usin->sin6_family && usin->sin6_family != AF_INET6) return(-EAFNOSUPPORT); + fl.fl6_flowlabel = 0; + if (np->sndflow) { + fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; + if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); + } + } + addr_type = ipv6_addr_type(&usin->sin6_addr); if (addr_type == IPV6_ADDR_ANY) { @@ -262,6 +274,7 @@ } ipv6_addr_copy(&np->daddr, daddr); + np->flow_label = fl.fl6_flowlabel; sk->dport = usin->sin6_port; @@ -271,25 +284,31 @@ */ fl.proto = IPPROTO_UDP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = NULL; + fl.fl6_dst = &np->daddr; + fl.fl6_src = &saddr; fl.oif = sk->bound_dev_if; fl.uli_u.ports.dport = sk->dport; fl.uli_u.ports.sport = sk->sport; - if (np->opt && np->opt->srcrt) { + if (flowlabel) { + if (flowlabel->opt && flowlabel->opt->srcrt) { + struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; + fl.fl6_dst = rt0->addr; + } + } else if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } dst = ip6_route_output(sk, &fl); if ((err = dst->error) != 0) { dst_release(dst); + fl6_sock_release(flowlabel); return err; } - ip6_dst_store(sk, dst, fl.nl_u.ip6_u.daddr); + ip6_dst_store(sk, dst, fl.fl6_dst); /* get the source adddress used in the apropriate device */ @@ -305,6 +324,7 @@ } sk->state = TCP_ESTABLISHED; } + fl6_sock_release(flowlabel); return err; } @@ -396,6 +416,7 @@ sin6 = (struct sockaddr_in6 *) msg->msg_name; sin6->sin6_family = AF_INET6; sin6->sin6_port = skb->h.uh->source; + sin6->sin6_flowinfo = 0; if (skb->protocol == __constant_htons(ETH_P_IP)) { ipv6_addr_set(&sin6->sin6_addr, 0, 0, @@ -734,10 +755,10 @@ struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; struct ipv6_txoptions *opt = NULL; + struct ip6_flowlabel *flowlabel = NULL; struct flowi fl; int addr_len = msg->msg_namelen; struct in6_addr *daddr; - struct in6_addr *saddr = NULL; int len = ulen + sizeof(struct udphdr); int addr_type; int hlimit = -1; @@ -752,23 +773,35 @@ if (msg->msg_flags & ~(MSG_DONTROUTE|MSG_DONTWAIT)) return(-EINVAL); - + + fl.fl6_flowlabel = 0; + if (sin6) { if (sin6->sin6_family == AF_INET) return udp_sendmsg(sk, msg, ulen); if (addr_len < sizeof(*sin6)) return(-EINVAL); - + if (sin6->sin6_family && sin6->sin6_family != AF_INET6) return(-EINVAL); if (sin6->sin6_port == 0) return(-EINVAL); - + udh.uh.dest = sin6->sin6_port; daddr = &sin6->sin6_addr; + if (np->sndflow) { + fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; + if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + daddr = &flowlabel->dst; + } + } + /* Otherwise it will be difficult to maintain sk->dst_cache. */ if (sk->state == TCP_ESTABLISHED && !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr)) @@ -776,38 +809,52 @@ } else { if (sk->state != TCP_ESTABLISHED) return(-ENOTCONN); - + udh.uh.dest = sk->dport; daddr = &sk->net_pinfo.af_inet6.daddr; + fl.fl6_flowlabel = np->flow_label; } - + addr_type = ipv6_addr_type(daddr); - + if (addr_type == IPV6_ADDR_MAPPED) { struct sockaddr_in sin; - + sin.sin_family = AF_INET; sin.sin_addr.s_addr = daddr->s6_addr32[3]; sin.sin_port = udh.uh.dest; msg->msg_name = (struct sockaddr *)(&sin); msg->msg_namelen = sizeof(sin); + fl6_sock_release(flowlabel); return udp_sendmsg(sk, msg, ulen); } - + udh.daddr = NULL; fl.oif = sk->bound_dev_if; - + fl.fl6_src = NULL; + if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); - err = datagram_send_ctl(msg, &fl.oif, &saddr, opt, &hlimit); - if (err < 0) + err = datagram_send_ctl(msg, &fl, opt, &hlimit); + if (err < 0) { + fl6_sock_release(flowlabel); return err; + } + if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + } + if (!(opt->opt_nflen|opt->opt_flen)) + opt = NULL; } - if (opt == NULL || !(opt->opt_nflen|opt->opt_flen)) + if (opt == NULL) opt = np->opt; + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); if (opt && opt->srcrt) udh.daddr = daddr; @@ -819,13 +866,14 @@ udh.pl_len = len; fl.proto = IPPROTO_UDP; - fl.nl_u.ip6_u.daddr = daddr; - fl.nl_u.ip6_u.saddr = saddr; + fl.fl6_dst = daddr; fl.uli_u.ports.dport = udh.uh.dest; fl.uli_u.ports.sport = udh.uh.source; err = ip6_build_xmit(sk, udpv6_getfrag, &udh, &fl, len, opt, hlimit, msg->msg_flags); + + fl6_sock_release(flowlabel); if (err < 0) return err; diff -u --recursive --new-file v2.2.6/linux/net/irda/af_irda.c linux/net/irda/af_irda.c --- v2.2.6/linux/net/irda/af_irda.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/af_irda.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun May 31 10:12:43 1998 - * Modified at: Wed Apr 7 17:32:27 1999 + * Modified at: Thu Apr 22 12:08:04 1999 * Modified by: Dag Brattli * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc. * @@ -39,6 +39,7 @@ #include #include #include +#include extern int irda_init(void); extern void irda_cleanup(void); @@ -237,8 +238,8 @@ * Got answer from remote LM-IAS * */ -static void irda_get_value_confirm(__u16 obj_id, struct ias_value *value, - void *priv) +static void irda_get_value_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv) { struct irda_sock *self; @@ -251,11 +252,14 @@ return; /* Check if request succeeded */ - if (!value) { + if (result != IAS_SUCCESS) { DEBUG(0, __FUNCTION__ "(), IAS query failed!\n"); + self->errno = result; + /* Wake up any processes waiting for result */ wake_up_interruptible(&self->ias_wait); + return; } @@ -673,7 +677,7 @@ self->mask = 0xffff; self->rx_flow = self->tx_flow = FLOW_START; self->max_sdu_size_rx = SAR_DISABLE; /* Default value */ - self->nslots = 6; /* Default for now */ + self->nslots = DISCOVERY_DEFAULT_SLOTS; /* Notify that we are using the irda module, so nobody removes it */ irda_mod_inc_use_count(); @@ -857,6 +861,12 @@ return copied; } +/* + * Function irda_shutdown (sk, how) + * + * + * + */ static int irda_shutdown( struct socket *sk, int how) { DEBUG( 0, __FUNCTION__ "()\n"); @@ -866,6 +876,12 @@ } +/* + * Function irda_poll (file, sock, wait) + * + * + * + */ unsigned int irda_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait) { diff -u --recursive --new-file v2.2.6/linux/net/irda/discovery.c linux/net/irda/discovery.c --- v2.2.6/linux/net/irda/discovery.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/discovery.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Apr 6 15:33:50 1999 - * Modified at: Tue Apr 6 20:26:46 1999 + * Modified at: Sun Apr 11 00:41:58 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -46,7 +46,7 @@ { discovery_t *old; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* Check if we have discovered this device before */ old = hashbin_remove(cachelog, discovery->daddr, NULL); @@ -67,7 +67,7 @@ { discovery_t *discovery; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* * If log is missing this means that IrLAP was unable to perform the @@ -100,7 +100,7 @@ { discovery_t *discovery, *curr; - DEBUG(3, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); discovery = (discovery_t *) hashbin_get_first(log); while (discovery != NULL) { diff -u --recursive --new-file v2.2.6/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c --- v2.2.6/linux/net/irda/ircomm/ircomm_common.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/ircomm/ircomm_common.c Sat Apr 24 17:50:06 1999 @@ -41,13 +41,21 @@ #include -static char *revision_date = "Tue Mar 2 02:03:58 1999"; +static char *revision_date = "Sun Apr 18 00:40:19 1999"; -static void ircomm_state_discovery(struct ircomm_cb *self, - IRCOMM_EVENT event, struct sk_buff *skb ); static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ); + +static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); + +static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); + +static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); + static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ); static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, @@ -63,13 +71,14 @@ static int ircomm_proc_read(char *buf, char **start, off_t offset, int len, int unused); +static void start_discovering(struct ircomm_cb *self); static void query_lsapsel(struct ircomm_cb * self); -static void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, - void *priv); +static void query_parameters(struct ircomm_cb *self); +static void queryias_done(struct ircomm_cb *self); +static void ircomm_getvalue_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv); -static __u32 ckey; -static __u32 skey; struct ircomm_cb *discovering_instance; /* @@ -86,8 +95,12 @@ static char *ircommstate[] = { - "DISCOVERY", "IDLE", + + "DISCOVERY_WAIT", + "QUERYPARAM_WAIT", + "QUERYLSAP_WAIT", + "WAITI", "WAITR", "CONN", @@ -126,6 +139,11 @@ "IRCOMM_DATA_REQUEST", "LMP_DATA_INDICATION", "IRCOMM_CONTROL_REQUEST", + + "DISCOVERY_INDICATION", + "GOT_PARAMETERS", + "GOT_LSAPSEL", + "QUERYIAS_ERROR", }; #ifdef CONFIG_PROC_FS @@ -141,8 +159,12 @@ static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb) = { - ircomm_state_discovery, ircomm_state_idle, + + ircomm_state_discoverywait, + ircomm_state_queryparamwait, + ircomm_state_querylsapwait, + ircomm_state_waiti, ircomm_state_waitr, ircomm_state_conn, @@ -376,6 +398,146 @@ } + +/* + * ircomm_discovery_indication() + * Remote device is discovered, try query the remote IAS to see which + * device it is, and which services it has. + */ + +static void ircomm_discovery_indication(discovery_t *discovery) +{ + struct ircomm_cb *self; + + self = discovering_instance; + if(self == NULL) + return; + ASSERT(self->magic == IRCOMM_MAGIC, return;); + + self->daddr = discovery->daddr; + self->saddr = discovery->saddr; + + DEBUG( 0, __FUNCTION__"():daddr=%08x\n", self->daddr); + + ircomm_do_event(self, DISCOVERY_INDICATION, NULL); + return; +} + +/* + * ircomm_getvalue_confirm() + * handler for iriap_getvaluebyclass_request() + */ +static void ircomm_getvalue_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv) +{ + struct ircomm_cb *self = (struct ircomm_cb *) priv; + struct sk_buff *skb= NULL; + __u8 *frame; + __u8 servicetype = 0 ; + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + /* Check if request succeeded */ + if (result != IAS_SUCCESS) { + DEBUG( 0, __FUNCTION__ "(), got NULL value!\n"); + ircomm_do_event(self, QUERYIAS_ERROR, NULL); + return; + } + + DEBUG(4, __FUNCTION__"():type(%d)\n", value->type); + + self->ias_type = value->type; + switch(value->type){ + case IAS_OCT_SEQ: + + DEBUG(4, __FUNCTION__"():got octet sequence:\n"); +#if 0 + { + int i; + for ( i=0;ilen;i++) + printk("%02x", + (__u8)(*(value->t.oct_seq + i))); + printk("\n"); + } +#endif + skb = dev_alloc_skb((value->len) + 2); + ASSERT(skb != NULL, ircomm_do_event(self, QUERYIAS_ERROR, NULL);return;); + frame = skb_put(skb,2); + /* MSB first */ + frame[0] = ( value->len >> 8 ) & 0xff; + frame[1] = value->len & 0xff; + + frame = skb_put(skb,value->len); + memcpy(frame, value->t.oct_seq, value->len); + ircomm_parse_tuples(self, skb, IAS_PARAM); + kfree_skb(skb); + + /* + * check if servicetype we want is available + */ + + DEBUG(0,__FUNCTION__"():peer capability is:\n"); + DEBUG(0,"3wire raw: %s\n", + ((self->peer_servicetype & THREE_WIRE_RAW) ? "yes":"no")); + DEBUG(0,"3wire : %s\n", + ((self->peer_servicetype & THREE_WIRE) ? "yes":"no")); + DEBUG(0,"9wire : %s\n", + ((self->peer_servicetype & NINE_WIRE) ? "yes":"no")); + DEBUG(0,"IEEE1284 : %s\n", + ((self->peer_servicetype & CENTRONICS) ? "yes":"no")); + + self->servicetype &= self->peer_servicetype; + if(!(self->servicetype)){ + DEBUG(0,__FUNCTION__"(): servicetype mismatch!\n"); + ircomm_do_event(self, QUERYIAS_ERROR, NULL); + break; + } + + /* + * then choose better one + */ + if(self->servicetype & THREE_WIRE_RAW) + servicetype = THREE_WIRE_RAW; + if(self->servicetype & THREE_WIRE) + servicetype = THREE_WIRE; + if(self->servicetype & NINE_WIRE) + servicetype = NINE_WIRE; + if(self->servicetype & CENTRONICS) + servicetype = CENTRONICS; + + self->servicetype = servicetype; + + /* enter next state */ + ircomm_do_event(self, GOT_PARAMETERS, NULL); + break; + + case IAS_INTEGER: + /* LsapSel seems to be sent to me */ + DEBUG(0, __FUNCTION__"():got lsapsel = %d\n", value->t.integer); + + if ( value->t.integer == -1){ + DEBUG( 0, __FUNCTION__"():invalid value!\n"); + ircomm_do_event(self, QUERYIAS_ERROR, NULL); + return; + } + self->dlsap = value->t.integer; + ircomm_do_event(self, GOT_LSAPSEL, NULL); + break; + + case IAS_MISSING: + DEBUG( 0, __FUNCTION__":got IAS_MISSING\n"); + ircomm_do_event(self, QUERYIAS_ERROR, NULL); + break; + + default: + DEBUG( 0, __FUNCTION__":got unknown (strange?)type!\n"); + ircomm_do_event(self, QUERYIAS_ERROR, NULL); + break; + } +} + + + /* * ---------------------------------------------------------------------- * Impl. of actions (descrived in section 7.4 of the reference) @@ -583,19 +745,6 @@ } -/* - * we currently need dummy (discovering) state for debugging, - * which state is not defined in the reference. - */ - -static void ircomm_state_discovery( struct ircomm_cb *self, - IRCOMM_EVENT event, struct sk_buff *skb ) -{ - printk(KERN_ERR __FUNCTION__"():why call me? something is wrong..\n"); - if(skb) - dev_kfree_skb( skb); -} - /* * ircomm_state_idle @@ -607,8 +756,11 @@ switch(event){ case IRCOMM_CONNECT_REQUEST: - ircomm_next_state(self, COMM_WAITI); - issue_connect_request( self, skb ); + /* ircomm_next_state(self, COMM_WAITI); */ + /* issue_connect_request( self, skb ); */ + + ircomm_next_state(self, COMM_DISCOVERY_WAIT); + start_discovering(self); break; case TTP_CONNECT_INDICATION: @@ -631,6 +783,121 @@ } /* + * ircomm_state_discoverywait + */ +static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ) +{ + switch(event){ + + case TTP_CONNECT_INDICATION: + + ircomm_next_state(self, COMM_WAITR); + queryias_done(self); + connect_indication( self, self->qos, skb); + break; + + case DISCOVERY_INDICATION: + ircomm_next_state(self, COMM_QUERYPARAM_WAIT); + query_parameters(self); + break; + + case IRCOMM_DISCONNECT_REQUEST: + ircomm_next_state(self, COMM_IDLE); + queryias_done(self); + break; + + case QUERYIAS_ERROR: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, NULL); + queryias_done(self); + break; + + default: + DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + +/* + * ircomm_state_queryparamwait + */ + +static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ) +{ + switch(event){ + + case TTP_CONNECT_INDICATION: + + ircomm_next_state(self, COMM_WAITR); + connect_indication( self, self->qos, skb); + break; + + case GOT_PARAMETERS: + + ircomm_next_state(self, COMM_QUERYLSAP_WAIT); + query_lsapsel( self ); + break; + + case IRCOMM_DISCONNECT_REQUEST: + ircomm_next_state(self, COMM_IDLE); + queryias_done(self); + break; + + case QUERYIAS_ERROR: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, NULL); + queryias_done(self); + break; + + default: + DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + +/* + * ircomm_state_querylsapwait + */ + +static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ) +{ + switch(event){ + + case TTP_CONNECT_INDICATION: + + ircomm_next_state(self, COMM_WAITR); + connect_indication( self, self->qos, skb); + break; + + case GOT_LSAPSEL: + + ircomm_next_state(self, COMM_WAITI); + queryias_done(self); + issue_connect_request( self, skb ); + break; + + case IRCOMM_DISCONNECT_REQUEST: + ircomm_next_state(self, COMM_IDLE); + queryias_done(self); + break; + + case QUERYIAS_ERROR: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, NULL); + queryias_done(self); + break; + + + default: + DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + +/* * ircomm_state_waiti */ @@ -688,6 +955,7 @@ case IRCOMM_DISCONNECT_REQUEST: ircomm_next_state(self, COMM_IDLE); issue_disconnect_request(self, skb); + queryias_done(self); break; case TTP_DISCONNECT_INDICATION: @@ -695,6 +963,19 @@ disconnect_indication(self, skb); break; + case DISCOVERY_INDICATION: + DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n"); + queryias_done(self); + break; + case GOT_PARAMETERS: + DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n"); + queryias_done(self); + break; + case GOT_LSAPSEL: + DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n"); + queryias_done(self); + break; + /* case LMP_DISCONNECT_INDICATION: */ /* disconnect_indication(); */ /* ircomm_next_state(self, COMM_IDLE); */ @@ -732,11 +1013,26 @@ case IRCOMM_DISCONNECT_REQUEST: ircomm_next_state(self, COMM_IDLE); issue_disconnect_request(self, skb); + queryias_done(self); break; /* case LM_DISCONNECT_INDICATION: */ /* disconnect_indication(); */ /* ircomm_next_state(self, COMM_IDLE); */ /* break; */ + + case DISCOVERY_INDICATION: + DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n"); + queryias_done(self); + break; + case GOT_PARAMETERS: + DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n"); + queryias_done(self); + break; + case GOT_LSAPSEL: + DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n"); + queryias_done(self); + break; + default: DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n", event, ircommevent[event]); @@ -744,6 +1040,7 @@ } + /* * ---------------------------------------------------------------------- * IrCOMM service interfaces and supporting functions @@ -751,172 +1048,97 @@ * ---------------------------------------------------------------------- */ -int ircomm_query_ias_and_connect(struct ircomm_cb *self, __u8 servicetype) -{ - int retval=0; - __u16 hints; - - ASSERT( self != NULL, return -EFAULT;); - ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;); - DEBUG(4,__FUNCTION__"():servicetype = %d\n",servicetype); +/* + * start_discovering() + * + * start discovering and enter DISCOVERY_WAIT state + */ - /* - * wait if another instance is discovering now - */ - if(discovering_instance){ - interruptible_sleep_on( &self->discovery_wait); - if(signal_pending(current)){ - return -EINTR; /* cought a signal */ - } - if(self->state == COMM_CONN) - return 0; /* got connected */ - } - ASSERT(discovering_instance == NULL, return -EFAULT;); - discovering_instance = self; +static void start_discovering(struct ircomm_cb *self) +{ + __u16 hints; + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + DEBUG(4,__FUNCTION__"():servicetype = %d\n",self->servicetype); - /* - * start discovering - */ + hints = irlmp_service_to_hint(S_COMM); DEBUG(0,__FUNCTION__"():start discovering..\n"); switch (ircomm_cs) { case 0: - skey = irlmp_register_service(hints); - ckey = irlmp_register_client(hints, ircomm_discovery_indication, + MOD_INC_USE_COUNT; + self->queryias_lock = 1; + discovering_instance = self; + self->skey = irlmp_register_service(hints); + self->ckey = irlmp_register_client(hints, ircomm_discovery_indication, NULL); break; case 1: /* client only */ + MOD_INC_USE_COUNT; + self->queryias_lock = 1; + discovering_instance = self; DEBUG( 0, __FUNCTION__"():client only mode\n"); - ckey = irlmp_register_client(hints, ircomm_discovery_indication, + self->ckey = irlmp_register_client(hints, ircomm_discovery_indication, NULL); break; case 2: /* server only */ default: DEBUG( 0, __FUNCTION__"():server only mode\n"); - skey = irlmp_register_service(hints); + self->skey = irlmp_register_service(hints); discovering_instance = NULL; - return 0; + break; } + + return; +} +/* + * queryias_done(self) + * + * called when discovery process got wrong results, completed, or terminated. + */ - /* - * waiting for discovery - */ - interruptible_sleep_on( &self->discovery_wait); - if(signal_pending(current)){ - retval = -EINTR; goto bailout; /* cought a signal */ +static void queryias_done(struct ircomm_cb *self) +{ + DEBUG(0, __FUNCTION__"():\n"); + if(self->queryias_lock){ + self->queryias_lock = 0; + discovering_instance = NULL; + MOD_DEC_USE_COUNT; + irlmp_unregister_client(self->ckey); } - if(self->state == COMM_CONN) - goto bailout; /* got connected */ + if(ircomm_cs != 1) + irlmp_unregister_service(self->skey); + return; +} - /* - * query Parameters field of IAS and waiting for answer - */ - self->servicetype = 0; + +static void query_parameters(struct ircomm_cb *self) +{ + DEBUG(0, __FUNCTION__"():querying IAS: Parameters..\n"); iriap_getvaluebyclass_request( "IrDA:IrCOMM", "Parameters", self->saddr, self->daddr, ircomm_getvalue_confirm, self ); +} - interruptible_sleep_on( &self->ias_wait); - if(signal_pending(current)){ - retval = -EINTR; goto bailout; /* cought a signal */ - } - if(self->state == COMM_CONN) - goto bailout; /* got connected */ - - - /* really got Parameters field? */ - if(self->ias_type != IAS_OCT_SEQ){ - retval = -EFAULT; - goto bailout; - } - - /* - * check if servicetype we want is available - */ - self->peer_cap = self->servicetype; - - DEBUG(0,__FUNCTION__"():peer capability is:\n"); - DEBUG(0,"3wire raw: %s\n",((self->servicetype & THREE_WIRE_RAW) ? "yes":"no")); - DEBUG(0,"3wire : %s\n",((self->servicetype & THREE_WIRE) ? "yes":"no")); - DEBUG(0,"9wire : %s\n",((self->servicetype & NINE_WIRE) ? "yes":"no")); - DEBUG(0,"IEEE1284 : %s\n",((self->servicetype & CENTRONICS) ? "yes":"no")); - - self->servicetype &= servicetype; - if(!(self->servicetype)){ - retval = -ENODEV; - goto bailout; - } - - /* - * then choose better one - */ - if(self->servicetype & THREE_WIRE_RAW) - servicetype = THREE_WIRE_RAW; - if(self->servicetype & THREE_WIRE) - servicetype = THREE_WIRE; - if(self->servicetype & NINE_WIRE) - servicetype = NINE_WIRE; - if(self->servicetype & CENTRONICS) - servicetype = CENTRONICS; +static void query_lsapsel(struct ircomm_cb * self) +{ + DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n"); - self->servicetype = servicetype; -#if 1 - /* - * waiting for discovery again - */ - interruptible_sleep_on( &self->discovery_wait); - if(signal_pending(current)){ - retval = -EINTR; goto bailout; /* cought a signal */ - } - if(self->state == COMM_CONN) - goto bailout; /* got connected */ -#endif - /* - * query lsapsel field and waiting for answer - */ - query_lsapsel(self); - interruptible_sleep_on( &self->ias_wait); - if(signal_pending(current)){ - retval = -EINTR; goto bailout; /* cought a signal */ - } - if(self->state == COMM_CONN) - goto bailout; /* got connected */ - - /* really got Lsapsel field? */ - if(self->ias_type != IAS_INTEGER){ - retval = -EFAULT; - goto bailout; - } -#if 1 - /* - * waiting for discovery again... - */ - interruptible_sleep_on( &self->discovery_wait); - if(signal_pending(current)){ - retval = -EINTR; goto bailout; /* cought a signal */ + if (!(self->servicetype & THREE_WIRE_RAW)) { + iriap_getvaluebyclass_request( + "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel", + self->saddr, self->daddr, + ircomm_getvalue_confirm, self ); + } else { + DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n"); } - if(self->state == COMM_CONN) - goto bailout; /* got connected */ -#endif - - /* succeed! ready to connect */ - discovering_instance = NULL; - ircomm_connect_request(self); - return 0; - - bailout: - /* failed. not ready to connect */ - discovering_instance = NULL; - irlmp_unregister_service(skey); - irlmp_unregister_client(ckey); - return retval; } /* @@ -926,7 +1148,7 @@ */ -void ircomm_connect_request(struct ircomm_cb *self) +void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) { /* * TODO:build a packet which contains "initial control parameters" @@ -939,7 +1161,8 @@ DEBUG(0, __FUNCTION__"():sending connect_request...\n"); - ircomm_control_request(self, SERVICETYPE); /*servictype*/ + self->servicetype= servicetype; + /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/ self->maxsdusize = SAR_DISABLE; ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL); @@ -986,6 +1209,7 @@ ASSERT( self->magic == IRCOMM_MAGIC, return;); DEBUG(0,__FUNCTION__"()\n"); +#if 0 /* unregister layer */ switch (ircomm_cs) { case 1: /* client only */ @@ -1001,6 +1225,7 @@ irlmp_unregister_service(skey); break; } +#endif self->disconnect_priority = priority; if(priority != P_HIGH) @@ -1353,7 +1578,7 @@ break; case SERVICETYPE: - self->servicetype = data[2]; + self->peer_servicetype = data[2]; break; case PORT_TYPE: @@ -1480,128 +1705,6 @@ * ---------------------------------------------------------------------- */ - - -/* - * ircomm_getvalue_confirm() - * handler for iriap_getvaluebyclass_request() - */ - -static void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, - void *priv) -{ - struct ircomm_cb *self = (struct ircomm_cb *) priv; - struct sk_buff *skb= NULL; - __u8 *frame; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRCOMM_MAGIC, return;); - - /* Check if request succeeded */ - if ( !value) { - DEBUG( 0, __FUNCTION__ "(), got NULL value!\n"); - return; - } - - DEBUG(4, __FUNCTION__"():type(%d)\n", value->type); - - self->ias_type = value->type; - switch(value->type){ - case IAS_OCT_SEQ: - - DEBUG(4, __FUNCTION__"():got octet sequence:\n"); -#if 0 - { - int i; - for ( i=0;ilen;i++) - printk("%02x", - (__u8)(*(value->t.oct_seq + i))); - printk("\n"); - } -#endif - skb = dev_alloc_skb((value->len) + 2); - ASSERT(skb != NULL, return;); - frame = skb_put(skb,2); - /* MSB first */ - frame[0] = ( value->len >> 8 ) & 0xff; - frame[1] = value->len & 0xff; - - frame = skb_put(skb,value->len); - memcpy(frame, value->t.oct_seq, value->len); - ircomm_parse_tuples(self, skb, IAS_PARAM); - kfree_skb(skb); - - wake_up_interruptible( &self->ias_wait); - break; - - case IAS_INTEGER: - /* LsapSel seems to be sent to me */ - DEBUG(0, __FUNCTION__"():got lsapsel = %d\n", value->t.integer); - - if ( value->t.integer == -1){ - DEBUG( 0, __FUNCTION__"():invalid value!\n"); - return; - } - - if(self->state == COMM_IDLE){ - self->dlsap = value->t.integer; - - wake_up_interruptible( &self->ias_wait); - } - break; - - case IAS_MISSING: - DEBUG( 0, __FUNCTION__":got IAS_MISSING\n"); - break; - - default: - DEBUG( 0, __FUNCTION__":got unknown (strange?)type!\n"); - break; - } -} - - -/* - * query_lsapsel() - * quering the remote IAS to ask which - * dlsap we should use - */ - -static void query_lsapsel(struct ircomm_cb * self) -{ - DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n"); - - if (!(self->servicetype & THREE_WIRE_RAW)) { - iriap_getvaluebyclass_request( - "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel", - self->saddr, self->daddr, - ircomm_getvalue_confirm, self ); - } else { - DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n"); - } -} - -/* - * ircomm_discovery_indication() - * Remote device is discovered, try query the remote IAS to see which - * device it is, and which services it has. - */ - -static void ircomm_discovery_indication(discovery_t *discovery) -{ - struct ircomm_cb *self; - - self = discovering_instance; - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRCOMM_MAGIC, return;); - - self->daddr = discovery->daddr; - self->saddr = discovery->saddr; - - DEBUG( 0, __FUNCTION__"():daddr=%08x\n", self->daddr); - - wake_up_interruptible( &self->discovery_wait); - return; -} struct ircomm_cb * ircomm_open_instance( struct notify_t client_notify) diff -u --recursive --new-file v2.2.6/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c --- v2.2.6/linux/net/irda/ircomm/irvtd_driver.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/ircomm/irvtd_driver.c Sat Apr 24 17:50:06 1999 @@ -51,7 +51,7 @@ static int irvtd_refcount; struct irvtd_cb **irvtd = NULL; -static char *revision_date = "Wed Mar 10 15:33:03 1999"; +static char *revision_date = "Sun Apr 18 17:31:53 1999"; /* @@ -74,6 +74,7 @@ void irvtd_start(struct tty_struct *tty); void irvtd_hangup(struct tty_struct *tty); void irvtd_flush_buffer(struct tty_struct *tty); +void irvtd_flush_chars(struct tty_struct *tty); static void change_speed(struct irvtd_cb *driver); static void irvtd_write_to_tty( struct irvtd_cb *); @@ -91,14 +92,6 @@ /* - * ---------------------------------------------------------------------- - * - * - - * ---------------------------------------------------------------------- - */ - -/* ********************************************************************** * * ircomm_receive_data() and friends @@ -122,11 +115,13 @@ struct sk_buff *skb; struct tty_struct *tty = driver->tty; + if(driver->rx_disable) + return; + skb = skb_dequeue(&driver->rxbuff); if(skb == NULL) return; /* there's nothing */ - /* * we should parse controlchannel field here. * (see process_data() in ircomm.c) @@ -244,6 +239,7 @@ irttp_flow_request(driver->comm->tsap, FLOW_STOP); driver->ttp_stoprx = 1; } + irvtd_write_to_tty(driver); return 0; } @@ -268,7 +264,7 @@ driver->timer.data = (unsigned long) driver; driver->timer.function = &irvtd_timer_expired; - driver->timer.expires = jiffies + (HZ / 20); /* 50msec */ + driver->timer.expires = jiffies + (HZ / 5); /* 200msec */ add_timer( &driver->timer); } @@ -282,13 +278,10 @@ ASSERT(driver->magic == IRVTD_MAGIC,return;); DEBUG(4, __FUNCTION__"()\n"); - if(!(driver->tty->hw_stopped) && !(driver->tx_disable)) - irvtd_send_data_request(driver); + irvtd_send_data_request(driver); + + irvtd_write_to_tty(driver); - if(!(driver->rx_disable)){ - irvtd_write_to_tty(driver); - } - /* start our timer again and again */ irvtd_start_timer(driver); } @@ -302,6 +295,8 @@ ASSERT(skb != NULL,return;); DEBUG(4, __FUNCTION__"()\n"); + if(driver->tty->hw_stopped || driver->tx_disable) + return; if(!skb->len) return; /* no data to send */ @@ -315,7 +310,7 @@ } #endif - DEBUG(4, __FUNCTION__"():sending %d bytes\n",(int)skb->len ); + DEBUG(1, __FUNCTION__"():sending %d octets\n",(int)skb->len ); driver->icount.tx += skb->len; err = ircomm_data_request(driver->comm, driver->txbuff); if (err){ @@ -327,7 +322,7 @@ /* allocate a new frame */ skb = driver->txbuff = dev_alloc_skb(driver->comm->max_txbuff_size); if (skb == NULL){ - printk(__FUNCTION__"():flush_txbuff():alloc_skb failed!\n"); + printk(__FUNCTION__"():alloc_skb failed!\n"); } else { skb_reserve(skb, COMM_HEADER_SIZE); } @@ -369,10 +364,11 @@ /* * sending initial control parameters here */ -#if 1 if(driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ + driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); + ircomm_control_request(driver->comm, SERVICETYPE); ircomm_control_request(driver->comm, DATA_RATE); ircomm_control_request(driver->comm, DATA_FORMAT); @@ -389,7 +385,6 @@ break; default: } -#endif driver->tx_disable = 0; wake_up_interruptible(&driver->open_wait); @@ -414,15 +409,27 @@ DEBUG(4,"irvtd_connect_indication:sending connect_response...\n"); - /*TODO: connect_response should send initialcontrolparameters! TH*/ - ircomm_connect_response(comm, NULL, SAR_DISABLE ); + driver->tx_disable = 0; + /* - * set default value + * send initial control parameters */ + if(driver->comm->servicetype == THREE_WIRE_RAW) + return; /* do nothing */ + + driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); + + switch(driver->comm->servicetype){ + case NINE_WIRE: + ircomm_control_request(driver->comm, DTELINE_STATE); + break; + default: + } + + driver->msr |= (MSR_DCD|MSR_RI|MSR_DSR|MSR_CTS); - driver->tx_disable = 0; wake_up_interruptible(&driver->open_wait); } @@ -445,7 +452,13 @@ DEBUG(4,"irvtd_disconnect_indication:\n"); driver->tx_disable = 1; - driver->disconnect_pend = 1; + if(skb_queue_empty(&driver->rxbuff)){ + /* disconnect */ + driver->rx_disable = 1; + tty_hangup(driver->tty); + } else { + driver->disconnect_pend = 1; + } } /* @@ -559,6 +572,12 @@ } break; + case FLOW_CONTROL: + case DATA_RATE: + case XON_XOFF_CHAR: + case DTELINE_STATE: + /* (maybe) nothing to do */ + break; default: DEBUG(0,__FUNCTION__"():PI = 0x%02x is not implemented\n", (int)driver->comm->pi); @@ -624,19 +643,6 @@ while (1) { current->state = TASK_INTERRUPTIBLE; - if (driver->comm->state == COMM_CONN){ - /* - * signal DTR and RTS - */ - driver->comm->dte = driver->mcr |= (MCR_DTR | - MCR_RTS | - DELTA_DTR| - DELTA_RTS ); - - ircomm_control_request(driver->comm, DTELINE_STATE); - } - - if (tty_hung_up_p(filp) || !(driver->flags & ASYNC_INITIALIZED)) { #ifdef DO_RESTART @@ -755,7 +761,6 @@ static int irvtd_startup(struct irvtd_cb *driver) { - int retval = 0; struct ias_object* obj; struct notify_t irvtd_notify; @@ -805,17 +810,13 @@ irias_insert_object( obj); driver->flags |= ASYNC_INITIALIZED; + /* * discover a peer device * TODO: other servicetype(i.e. 3wire,3wireraw) support */ - retval = ircomm_query_ias_and_connect(driver->comm, NINE_WIRE); - if(retval){ - DEBUG(0, __FUNCTION__"(): ircomm_query_ias returns %d\n", - retval); - return retval; - } - + ircomm_connect_request(driver->comm, NINE_WIRE); + /* * TODO:we have to initialize control-channel here! * i.e.set something into RTS,CTS and so on.... @@ -931,7 +932,7 @@ ASSERT(driver->magic == IRVTD_MAGIC, return;); ASSERT(driver->comm != NULL, return;); - DEBUG(0, __FUNCTION__"():\n"); + DEBUG(1, __FUNCTION__"():\n"); if(!tty->closing) return; /* nothing to do */ @@ -944,7 +945,7 @@ orig_jiffies = jiffies; while (driver->comm->tsap->disconnect_pend) { - DEBUG(0, __FUNCTION__"():wait..\n"); + DEBUG(1, __FUNCTION__"():wait..\n"); current->state = TASK_INTERRUPTIBLE; current->counter = 0; /* make us low-priority */ schedule_timeout(HZ); /* 1sec */ @@ -964,7 +965,7 @@ if (!(driver->flags & ASYNC_INITIALIZED)) return; - DEBUG(0,__FUNCTION__"()\n"); + DEBUG(1,__FUNCTION__"()\n"); /* * This comment is written in serial.c: @@ -1017,7 +1018,7 @@ int line; unsigned long flags; - DEBUG(0, __FUNCTION__"():refcount= %d\n",irvtd_refcount); + DEBUG(1, __FUNCTION__"():refcount= %d\n",irvtd_refcount); ASSERT(driver != NULL, return;); ASSERT(driver->magic == IRVTD_MAGIC, return;); @@ -1030,7 +1031,7 @@ * upper tty layer caught a HUP signal and called irvtd_hangup() * before. so we do nothing here. */ - DEBUG(0, __FUNCTION__"():tty_hung_up_p.\n"); + DEBUG(1, __FUNCTION__"():tty_hung_up_p.\n"); MOD_DEC_USE_COUNT; restore_flags(flags); return; @@ -1142,7 +1143,6 @@ DEBUG(4, __FUNCTION__"()\n"); - save_flags(flags); while(1){ cli(); @@ -1164,11 +1164,23 @@ wrote += c; count -= c; buf += c; + irvtd_send_data_request(driver); } restore_flags(flags); return (wrote); } +void irvtd_flush_chars(struct tty_struct *tty) +{ + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + ASSERT( driver != NULL, return;); + ASSERT( driver->magic == IRVTD_MAGIC, return;); + + DEBUG(4, __FUNCTION__"()\n"); + irvtd_send_data_request(driver); +} + + /* * Function irvtd_put_char (tty, ch) * @@ -1606,14 +1618,14 @@ static void irvtd_send_xchar(struct tty_struct *tty, char ch){ - DEBUG(0, __FUNCTION__"():\n"); + DEBUG(1, __FUNCTION__"():\n"); irvtd_put_char(tty, ch); } void irvtd_throttle(struct tty_struct *tty){ struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; - DEBUG(0, "irvtd_throttle:\n"); + DEBUG(1, "irvtd_throttle:\n"); if (I_IXOFF(tty)) irvtd_put_char(tty, STOP_CHAR(tty)); @@ -1628,7 +1640,7 @@ void irvtd_unthrottle(struct tty_struct *tty){ struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; - DEBUG(0, "irvtd_unthrottle:\n"); + DEBUG(1, "irvtd_unthrottle:\n"); if (I_IXOFF(tty)) irvtd_put_char(tty, START_CHAR(tty)); @@ -1760,7 +1772,7 @@ irvtd_drv.close = irvtd_close; irvtd_drv.write = irvtd_write; irvtd_drv.put_char = irvtd_put_char; - irvtd_drv.flush_chars = NULL; + irvtd_drv.flush_chars = irvtd_flush_chars; irvtd_drv.write_room = irvtd_write_room; irvtd_drv.chars_in_buffer = irvtd_chars_in_buffer; irvtd_drv.flush_buffer = irvtd_flush_buffer; @@ -1916,7 +1928,7 @@ memset( irvtd[i], 0, sizeof(struct irvtd_cb)); irvtd[i]->magic = IRVTD_MAGIC; irvtd[i]->line = i; - irvtd[i]->closing_wait = 30*HZ ; + irvtd[i]->closing_wait = 10*HZ ; irvtd[i]->close_delay = 5*HZ/10 ; } diff -u --recursive --new-file v2.2.6/linux/net/irda/irda_device.c linux/net/irda/irda_device.c --- v2.2.6/linux/net/irda/irda_device.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irda_device.c Sat Apr 24 17:50:06 1999 @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irda_device.c - * Version: 0.4 + * Version: 0.5 * Description: Abstract device driver layer and helper functions * Status: Experimental. * Author: Dag Brattli * Created at: Wed Sep 2 20:22:08 1998 - * Modified at: Wed Apr 7 17:16:54 1999 + * Modified at: Wed Apr 21 09:48:19 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -129,26 +129,28 @@ /* Allocate memory if needed */ if (self->rx_buff.truesize > 0) { - self->rx_buff.data = ( __u8 *) kmalloc(self->rx_buff.truesize, + self->rx_buff.head = ( __u8 *) kmalloc(self->rx_buff.truesize, self->rx_buff.flags); - if (self->rx_buff.data == NULL) + if (self->rx_buff.head == NULL) return -ENOMEM; - memset(self->rx_buff.data, 0, self->rx_buff.truesize); + memset(self->rx_buff.head, 0, self->rx_buff.truesize); } if (self->tx_buff.truesize > 0) { - self->tx_buff.data = ( __u8 *) kmalloc(self->tx_buff.truesize, + self->tx_buff.head = ( __u8 *) kmalloc(self->tx_buff.truesize, self->tx_buff.flags); - if (self->tx_buff.data == NULL) + if (self->tx_buff.head == NULL) return -ENOMEM; - memset(self->tx_buff.data, 0, self->tx_buff.truesize); + memset(self->tx_buff.head, 0, self->tx_buff.truesize); } self->magic = IRDA_DEVICE_MAGIC; self->rx_buff.in_frame = FALSE; self->rx_buff.state = OUTSIDE_FRAME; + self->tx_buff.data = self->tx_buff.head; + self->rx_buff.data = self->rx_buff.head; /* Initialize timers */ init_timer(&self->media_busy_timer); @@ -184,7 +186,7 @@ /* Open network device */ dev_open(&self->netdev); - printk("IrDA device %s registered.\n", self->name); + MESSAGE("IrDA: Registred device %s\n", self->name); irda_device_set_media_busy(self, FALSE); @@ -197,8 +199,6 @@ /* It's now safe to initilize the saddr */ memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4); - DEBUG(4, __FUNCTION__ "()->\n"); - return 0; } @@ -226,11 +226,11 @@ /* Stop timers */ del_timer(&self->media_busy_timer); - if (self->tx_buff.data) - kfree(self->tx_buff.data); + if (self->tx_buff.head) + kfree(self->tx_buff.head); - if (self->rx_buff.data) - kfree(self->rx_buff.data); + if (self->rx_buff.head) + kfree(self->rx_buff.head); self->magic = 0; } @@ -463,26 +463,6 @@ } /* - * Function irda_get_mtt (skb) - * - * Utility function for getting the minimum turnaround time out of - * the skb, where it has been hidden in the cb field. - */ -inline unsigned short irda_get_mtt(struct sk_buff *skb) -{ - unsigned short mtt; - - if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) - mtt = 10000; - else - mtt = ((struct irlap_skb_cb *)(skb->cb))->mtt; - - ASSERT(mtt <= 10000, return 10000;); - - return mtt; -} - -/* * Function setup_dma (idev, buffer, count, mode) * * Setup the DMA channel @@ -561,7 +541,6 @@ self->description); len += irda_device_print_flags(self, buf+len); - len += sprintf(buf+len, "\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n"); len += sprintf(buf+len, "\t%d\t", diff -u --recursive --new-file v2.2.6/linux/net/irda/iriap.c linux/net/irda/iriap.c --- v2.2.6/linux/net/irda/iriap.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/iriap.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Tue Mar 23 19:38:46 1999 + * Modified at: Fri Apr 23 09:57:12 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -172,6 +173,7 @@ DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n"); return NULL; } + slsap_sel = lsap->slsap_sel; DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel); self->magic = IAS_MAGIC; @@ -179,7 +181,7 @@ self->slsap_sel = slsap_sel; self->mode = mode; - /* init_timer( &self->watchdog_timer); */ + init_timer( &self->watchdog_timer); hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL); @@ -204,7 +206,7 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == IAS_MAGIC, return;); - /* del_timer( &self->watchdog_timer); */ + del_timer( &self->watchdog_timer); self->magic = 0; @@ -258,7 +260,7 @@ ASSERT( iriap != NULL, return;); - /* del_timer( &self->watchdog_timer); */ + del_timer( &self->watchdog_timer); if ( self->mode == IAS_CLIENT) { DEBUG( 4, __FUNCTION__ "(), disconnect as client\n"); @@ -267,8 +269,8 @@ * Inform service user that the request failed by sending * it a NULL value. */ - if ( self->confirm) - self->confirm( 0, NULL, self->priv); + if (self->confirm) + self->confirm(IAS_DISCONNECT, 0, NULL, self->priv); iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, @@ -348,9 +350,9 @@ * Retreive all values from attribute in all objects with given class * name */ -void iriap_getvaluebyclass_request( char *name, char *attr, - __u32 saddr, __u32 daddr, - CONFIRM_CALLBACK callback, void *priv) +void iriap_getvaluebyclass_request(char *name, char *attr, + __u32 saddr, __u32 daddr, + CONFIRM_CALLBACK callback, void *priv) { struct sk_buff *skb; struct iriap_cb *self; @@ -358,9 +360,9 @@ int name_len, attr_len; __u8 slsap = LSAP_ANY; /* Source LSAP to use */ - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - self = iriap_open( slsap, IAS_CLIENT); + self = iriap_open(slsap, IAS_CLIENT); if (!self) return; @@ -376,29 +378,29 @@ */ self->operation = GET_VALUE_BY_CLASS; - /* Give ourselves 7 secs to finish this operation */ - /* iriap_start_watchdog_timer( self, 700); */ + /* Give ourselves 10 secs to finish this operation */ + iriap_start_watchdog_timer(self, 10*HZ); skb = dev_alloc_skb( 64); if (!skb) return; - name_len = strlen( name); - attr_len = strlen( attr); + name_len = strlen(name); + attr_len = strlen(attr); /* Reserve space for MUX and LAP header */ - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); - skb_put( skb, 3+name_len+attr_len); + skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_put(skb, 3+name_len+attr_len); frame = skb->data; /* Build frame */ frame[0] = IAP_LST | GET_VALUE_BY_CLASS; frame[1] = name_len; /* Insert length of name */ - memcpy( frame+2, name, name_len); /* Insert name */ + memcpy(frame+2, name, name_len); /* Insert name */ frame[2+name_len] = attr_len; /* Insert length of attr */ - memcpy( frame+3+name_len, attr, attr_len); /* Insert attr */ + memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */ - iriap_do_client_event( self, IAP_CALL_REQUEST_GVBC, skb); + iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb); } /* @@ -415,7 +417,6 @@ int charset; __u32 value_len; __u32 tmp_cpu32; - __u16 tmp_cpu16; __u16 obj_id; __u16 len; __u8 type; @@ -430,14 +431,14 @@ n = 2; /* Get length, MSB first */ - memcpy(&len, fp+n, 2); n += 2; - be16_to_cpus(&len); + len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2; DEBUG(4, __FUNCTION__ "(), len=%d\n", len); /* Get object ID, MSB first */ - memcpy(&obj_id, fp+n, 2); n += 2; - be16_to_cpus(&obj_id); + obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2; +/* memcpy(&obj_id, fp+n, 2); n += 2; */ +/* be16_to_cpus(&obj_id); */ type = fp[n++]; DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type); @@ -484,9 +485,8 @@ value = irias_new_string_value(fp+n); break; case IAS_OCT_SEQ: - memcpy(&tmp_cpu16, fp+n, 2); n += 2; - be16_to_cpus(&tmp_cpu16); - value_len = tmp_cpu16; + value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); + n += 2; /* FIXME:should be 1024, but.... */ DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len); @@ -499,11 +499,11 @@ break; } - if (self->confirm) - self->confirm(obj_id, value, self->priv); - /* Finished, close connection! */ iriap_disconnect_request(self); + + if (self->confirm) + self->confirm(IAS_SUCCESS, obj_id, value, self->priv); } /* @@ -550,7 +550,7 @@ fp[n++] = ret_code; /* Insert list length (MSB first) */ - tmp_be16 = __constant_htons( 0x0001); + tmp_be16 = __constant_htons(0x0001); memcpy(fp+n, &tmp_be16, 2); n += 2; /* Insert object identifier ( MSB first) */ @@ -703,17 +703,17 @@ { struct iriap_cb *self; - self = ( struct iriap_cb *) instance; + self = (struct iriap_cb *) instance; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); - ASSERT( userdata != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); + ASSERT(userdata != NULL, return;); - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* del_timer( &self->watchdog_timer); */ - iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata); + iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata); } /* @@ -778,7 +778,7 @@ } if (~opcode & IAP_ACK) { - DEBUG(0, __FUNCTION__ "() Got ack frame!\n"); + DEBUG(2, __FUNCTION__ "() Got ack frame!\n"); /* return; */ } @@ -797,9 +797,21 @@ break; case IAS_CLASS_UNKNOWN: printk(KERN_WARNING "IrIAP No such class!\n"); + /* Finished, close connection! */ + iriap_disconnect_request(self); + + if (self->confirm) + self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, + self->priv); break; case IAS_ATTRIB_UNKNOWN: printk(KERN_WARNING "IrIAP No such attribute!\n"); + /* Finished, close connection! */ + iriap_disconnect_request(self); + + if (self->confirm) + self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, + self->priv); break; } iriap_do_call_event( self, IAP_RECV_F_LST, skb); @@ -854,18 +866,20 @@ } } +/* + * Function iriap_watchdog_timer_expired (data) + * + * + * + */ void iriap_watchdog_timer_expired( unsigned long data) { struct iriap_cb *self = ( struct iriap_cb *) data; - DEBUG( 0, __FUNCTION__ "()\n"); - - return; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); - DEBUG( 0, __FUNCTION__ "() Timeout! closing myself!\n"); + DEBUG(0, __FUNCTION__ "() Timeout! closing myself!\n"); iriap_close( self); } diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c --- v2.2.6/linux/net/irda/irlan/irlan_client.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlan/irlan_client.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Wed Apr 7 16:56:35 1999 + * Modified at: Thu Apr 22 23:03:55 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -106,7 +105,7 @@ { struct irmanager_event mgr_event; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -122,8 +121,8 @@ if (self->dev.start) { /* Open TSAPs */ irlan_client_open_ctrl_tsap(self); - irlan_provider_open_ctrl_tsap(self); - irlan_open_data_tsap(self); + irlan_provider_open_ctrl_tsap(self); + irlan_open_data_tsap(self); irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL); } else if (self->notify_irmanager) { @@ -162,7 +161,7 @@ struct irlan_cb *self, *entry; __u32 saddr, daddr; - DEBUG(2, __FUNCTION__"()\n"); + DEBUG(0, __FUNCTION__"()\n"); ASSERT(irlan != NULL, return;); ASSERT(discovery != NULL, return;); @@ -171,8 +170,7 @@ daddr = discovery->daddr; /* - * Check if we already have an instance for dealing with this - * provider. + * Check if we already dealing with this provider. */ self = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL); if (self) { @@ -190,7 +188,7 @@ */ self = hashbin_find(irlan, DEV_ADDR_ANY, NULL); if (self) { - DEBUG(2, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n"); + DEBUG(0, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n"); /* * Rehash instance, now we have a client (daddr) to serve. */ @@ -200,27 +198,16 @@ self->daddr = daddr; self->saddr = saddr; - DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); + DEBUG(0, __FUNCTION__ "(), daddr=%08x\n", self->daddr); hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); /* Check if network device has been registered */ if (!self->netdev_registered) irlan_register_netdev(self); - /* Remember that we might have to start a new provider */ - self->client.start_new_provider = TRUE; - } else { - DEBUG(2, __FUNCTION__ "(), Found none, starting new one!\n"); - /* No instance available, so we have to start one! */ - self = irlan_open(saddr, daddr, TRUE); - if (!self) { - DEBUG(2, __FUNCTION__ "(), irlan_open failed!\n"); - return; - } - ASSERT( self != NULL, return;); + /* Restart watchdog timer */ + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); } - /* Restart watchdog timer */ - irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); } /* @@ -367,13 +354,12 @@ } /* - * Function irlan_client_extract_params (skb) + * Function irlan_client_parse_response (self, skb) * * Extract all parameters from received buffer, then feed them to * check_params for parsing - * */ -void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb) +void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb) { __u8 *frame; __u8 *ptr; @@ -392,7 +378,7 @@ ASSERT(self->magic == IRLAN_MAGIC, return;); if (!skb) { - DEBUG(2, __FUNCTION__ "(), Got NULL skb!\n"); + ERROR( __FUNCTION__ "(), Got NULL skb!\n"); return; } frame = skb->data; @@ -423,7 +409,7 @@ /* For all parameters */ for (i=0; idev.dev_addr[i] = bytes[i]; - -#ifdef CONFIG_IRLAN_GRATUITOUS_ARP - /* - * When we get a new MAC address do a gratuitous ARP. This - * is useful if we have changed access points on the same - * subnet. - */ - DEBUG(4, "IrLAN: Sending gratuitous ARP\n"); - in_dev = self->dev.ip_ptr; - arp_send(ARPOP_REQUEST, ETH_P_ARP, - in_dev->ifa_list->ifa_address, - &self->dev, - in_dev->ifa_list->ifa_address, - NULL, self->dev.dev_addr, NULL); -#endif } } @@ -574,8 +542,8 @@ * Got results from remote LM-IAS * */ -void irlan_client_get_value_confirm(__u16 obj_id, struct ias_value *value, - void *priv) +void irlan_client_get_value_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv) { struct irlan_cb *self; @@ -587,7 +555,7 @@ ASSERT(self->magic == IRLAN_MAGIC, return;); /* Check if request succeeded */ - if (!value) { + if (result != IAS_SUCCESS) { DEBUG(2, __FUNCTION__ "(), got NULL value!\n"); irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL); diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c --- v2.2.6/linux/net/irda/irlan/irlan_client_event.c Wed Mar 10 15:29:52 1999 +++ linux/net/irda/irlan/irlan_client_event.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Feb 4 16:08:07 1999 + * Modified at: Thu Apr 22 12:23:22 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -226,7 +226,7 @@ case IRLAN_DATA_INDICATION: ASSERT(skb != NULL, return -1;); - irlan_client_extract_params(self, skb); + irlan_client_parse_response(self, skb); irlan_next_client_state(self, IRLAN_MEDIA); @@ -266,7 +266,7 @@ switch(event) { case IRLAN_DATA_INDICATION: - irlan_client_extract_params(self, skb); + irlan_client_parse_response(self, skb); irlan_open_data_channel(self); irlan_next_client_state(self, IRLAN_OPEN); break; @@ -305,7 +305,7 @@ switch(event) { case IRLAN_DATA_INDICATION: - irlan_client_extract_params(self, skb); + irlan_client_parse_response(self, skb); /* * Check if we have got the remote TSAP for data @@ -336,11 +336,6 @@ IRLAN_MTU, NULL); irlan_next_client_state(self, IRLAN_DATA); - - if (self->client.start_new_provider) { - irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE); - self->client.start_new_provider = FALSE; - } break; default: DEBUG(2, __FUNCTION__ "(), unknown access type!\n"); @@ -468,7 +463,7 @@ switch(event) { case IRLAN_DATA_INDICATION: - irlan_client_extract_params(self, skb); + irlan_client_parse_response(self, skb); break; case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */ case IRLAN_LAP_DISCONNECT: diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c --- v2.2.6/linux/net/irda/irlan/irlan_common.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlan/irlan_common.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Wed Apr 7 17:03:21 1999 + * Modified at: Thu Apr 22 23:13:47 1999 * Modified by: Dag Brattli * * Copyright (c) 1997 Dag Brattli , All Rights Reserved. @@ -112,9 +112,11 @@ void irlan_watchdog_timer_expired(unsigned long data) { struct irmanager_event mgr_event; - struct irlan_cb *self = (struct irlan_cb *) data; + struct irlan_cb *self, *entry; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); + + self = (struct irlan_cb *) data; ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -132,147 +134,38 @@ * by the user. */ self->notify_irmanager = FALSE; - } else - irlan_close(self); -} - -void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout) -{ - DEBUG(4, __FUNCTION__ "()\n"); - - irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self, - irlan_watchdog_timer_expired); -} - -/* - * Function irlan_eth_open (dev) - * - * Network device has been opened by user - * - */ -static int irlan_eth_open(struct device *dev) -{ - struct irlan_cb *self; - - DEBUG(4, __FUNCTION__ "()\n"); - - ASSERT(dev != NULL, return -1;); - - self = (struct irlan_cb *) dev->priv; - - ASSERT(self != NULL, return -1;); - - /* Ready to play! */ -/* dev->tbusy = 0; */ /* Wait until data link is ready */ - dev->interrupt = 0; - dev->start = 1; - - self->notify_irmanager = TRUE; + } else { + DEBUG(0, __FUNCTION__ "(), recycling instance!\n"); + if (self->netdev_registered) { + DEBUG(0, __FUNCTION__ "(), removing netdev!\n"); + unregister_netdev(&self->dev); + self->netdev_registered = FALSE; + } + + /* Unbind from daddr */ + entry = hashbin_remove(irlan, self->daddr, NULL); + ASSERT(entry == self, return;); - /* We are now open, so time to do some work */ - irlan_client_wakeup(self, self->saddr, self->daddr); + self->daddr = DEV_ADDR_ANY; + self->saddr = DEV_ADDR_ANY; - MOD_INC_USE_COUNT; - - return 0; + DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); + hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); + } } /* - * Function irlan_eth_close (dev) + * Function irlan_start_watchdog_timer (self, timeout) * - * Stop the ether network device, his function will usually be called by - * ifconfig down. We should now disconnect the link, We start the - * close timer, so that the instance will be removed if we are unable - * to discover the remote device after the disconnect. - */ -static int irlan_eth_close(struct device *dev) -{ - struct irlan_cb *self = (struct irlan_cb *) dev->priv; - - DEBUG(4, __FUNCTION__ "()\n"); - - /* Stop device */ - dev->tbusy = 1; - dev->start = 0; - - MOD_DEC_USE_COUNT; - - irlan_close_data_channel(self); - - irlan_close_tsaps(self); - - irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL); - irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL); - - irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); - - /* Device closed by user! */ - if (self->notify_irmanager) - self->notify_irmanager = FALSE; - else - self->notify_irmanager = TRUE; - - return 0; -} -/* - * Function irlan_eth_init (dev) - * - * The network device initialization function. + * * */ -int irlan_eth_init(struct device *dev) +void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout) { - struct irmanager_event mgr_event; - struct irlan_cb *self; - - DEBUG(4, __FUNCTION__"()\n"); - - ASSERT(dev != NULL, return -1;); - - self = (struct irlan_cb *) dev->priv; - - dev->open = irlan_eth_open; - dev->stop = irlan_eth_close; - dev->hard_start_xmit = irlan_eth_xmit; - dev->get_stats = irlan_eth_get_stats; - dev->set_multicast_list = irlan_eth_set_multicast_list; - - dev->tbusy = 1; - - ether_setup(dev); + DEBUG(4, __FUNCTION__ "()\n"); - dev->tx_queue_len = TTP_MAX_QUEUE; - -#if 0 - /* - * OK, since we are emulating an IrLAN sever we will have to give - * ourself an ethernet address! - * FIXME: this must be more dynamically - */ - dev->dev_addr[0] = 0x40; - dev->dev_addr[1] = 0x00; - dev->dev_addr[2] = 0x00; - dev->dev_addr[3] = 0x00; - dev->dev_addr[4] = 0x23; - dev->dev_addr[5] = 0x45; -#endif - /* - * Network device has now been registered, so tell irmanager about - * it, so it can be configured with network parameters - */ - mgr_event.event = EVENT_IRLAN_START; - sprintf(mgr_event.devname, "%s", self->ifname); - irmanager_notify(&mgr_event); - - /* - * We set this so that we only notify once, since if - * configuration of the network device fails, the user - * will have to sort it out first anyway. No need to - * try again. - */ - self->notify_irmanager = FALSE; - - return 0; + irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self, + irlan_watchdog_timer_expired); } /* @@ -312,8 +205,12 @@ /* Start the first IrLAN instance */ new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE); + irlan_open_data_tsap(new); + irlan_client_open_ctrl_tsap(new); + irlan_provider_open_ctrl_tsap(new); + /* Do some fast discovery! */ - irlmp_discovery_request(8); + irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); return 0; } @@ -345,7 +242,7 @@ { int i=0; - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); /* Check if we should call the device eth or irlan */ if (!eth) { @@ -416,10 +313,6 @@ irlan_next_client_state(self, IRLAN_IDLE); irlan_next_provider_state(self, IRLAN_IDLE); - irlan_open_data_tsap(self); - irlan_provider_open_ctrl_tsap(self); - irlan_client_open_ctrl_tsap(self); - /* Register network device now, or wait until some later time? */ if (netdev) irlan_register_netdev(self); @@ -436,7 +329,7 @@ */ static void __irlan_close(struct irlan_cb *self) { - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -447,11 +340,13 @@ /* Close all open connections and remove TSAPs */ irlan_close_tsaps(self); - if (self->netdev_registered) + if (self->netdev_registered) { unregister_netdev(&self->dev); + self->netdev_registered = FALSE; + } self->magic = 0; - kfree(self); + kfree(self); } /* @@ -464,7 +359,7 @@ { struct irlan_cb *entry; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -572,7 +467,7 @@ switch(reason) { case LM_USER_REQUEST: /* User request */ - irlan_close(self); + //irlan_close(self); break; case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */ irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); @@ -636,7 +531,7 @@ self->stsap_sel_data = self->tsap_data->stsap_sel; } -static void irlan_close_tsaps(struct irlan_cb *self) +void irlan_close_tsaps(struct irlan_cb *self) { DEBUG(4, __FUNCTION__ "()\n"); @@ -1122,12 +1017,12 @@ } /* - * Function irlan_get_response_param (buf, param, value) + * Function irlan_extract_param (buf, name, value, len) * * Extracts a single parameter name/value pair from buffer and updates * the buffer pointer to point to the next name/value pair. */ -int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len) +int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) { __u8 name_len; __u16 val_len; @@ -1274,6 +1169,20 @@ printk(KERN_WARNING "Asynchronous status\n"); break; } +} + +void irlan_mod_inc_use_count(void) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +void irlan_mod_dec_use_count(void) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif } #ifdef MODULE diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c --- v2.2.6/linux/net/irda/irlan/irlan_eth.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlan/irlan_eth.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Oct 15 08:37:58 1998 - * Modified at: Mon Mar 22 17:41:59 1999 + * Modified at: Thu Apr 22 14:26:39 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, @@ -27,15 +27,150 @@ #include #include +#include #include #include #include #include #include +#include +#include #include /* + * Function irlan_eth_init (dev) + * + * The network device initialization function. + * + */ +int irlan_eth_init(struct device *dev) +{ + struct irmanager_event mgr_event; + struct irlan_cb *self; + + DEBUG(0, __FUNCTION__"()\n"); + + ASSERT(dev != NULL, return -1;); + + self = (struct irlan_cb *) dev->priv; + + dev->open = irlan_eth_open; + dev->stop = irlan_eth_close; + dev->hard_start_xmit = irlan_eth_xmit; + dev->get_stats = irlan_eth_get_stats; + dev->set_multicast_list = irlan_eth_set_multicast_list; + + dev->tbusy = 1; + + ether_setup(dev); + + dev->tx_queue_len = TTP_MAX_QUEUE; + +#if 0 + /* + * OK, since we are emulating an IrLAN sever we will have to give + * ourself an ethernet address! + * FIXME: this must be more dynamically + */ + dev->dev_addr[0] = 0x40; + dev->dev_addr[1] = 0x00; + dev->dev_addr[2] = 0x00; + dev->dev_addr[3] = 0x00; + dev->dev_addr[4] = 0x23; + dev->dev_addr[5] = 0x45; +#endif + /* + * Network device has now been registered, so tell irmanager about + * it, so it can be configured with network parameters + */ + mgr_event.event = EVENT_IRLAN_START; + sprintf(mgr_event.devname, "%s", self->ifname); + irmanager_notify(&mgr_event); + + /* + * We set this so that we only notify once, since if + * configuration of the network device fails, the user + * will have to sort it out first anyway. No need to + * try again. + */ + self->notify_irmanager = FALSE; + + return 0; +} + +/* + * Function irlan_eth_open (dev) + * + * Network device has been opened by user + * + */ +int irlan_eth_open(struct device *dev) +{ + struct irlan_cb *self; + + DEBUG(0, __FUNCTION__ "()\n"); + + ASSERT(dev != NULL, return -1;); + + self = (struct irlan_cb *) dev->priv; + + ASSERT(self != NULL, return -1;); + + /* Ready to play! */ +/* dev->tbusy = 0; */ /* Wait until data link is ready */ + dev->interrupt = 0; + dev->start = 1; + + self->notify_irmanager = TRUE; + + /* We are now open, so time to do some work */ + irlan_client_wakeup(self, self->saddr, self->daddr); + + irlan_mod_inc_use_count(); + + return 0; +} + +/* + * Function irlan_eth_close (dev) + * + * Stop the ether network device, his function will usually be called by + * ifconfig down. We should now disconnect the link, We start the + * close timer, so that the instance will be removed if we are unable + * to discover the remote device after the disconnect. + */ +int irlan_eth_close(struct device *dev) +{ + struct irlan_cb *self = (struct irlan_cb *) dev->priv; + + DEBUG(0, __FUNCTION__ "()\n"); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + irlan_mod_dec_use_count(); + + irlan_close_data_channel(self); + + irlan_close_tsaps(self); + + irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL); + irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL); + + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); + + /* Device closed by user! */ + if (self->notify_irmanager) + self->notify_irmanager = FALSE; + else + self->notify_irmanager = TRUE; + + return 0; +} + +/* * Function irlan_eth_tx (skb) * * Transmits ethernet frames over IrDA link. @@ -217,6 +352,30 @@ memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); /* return 0; */ +} + +/* + * Function irlan_etc_send_gratuitous_arp (dev) + * + * Send gratuitous ARP to announce that we have changed + * hardware address, so that all peers updates their ARP tables + */ +void irlan_etc_send_gratuitous_arp(struct device *dev) +{ + struct in_device *in_dev; + + /* + * When we get a new MAC address do a gratuitous ARP. This + * is useful if we have changed access points on the same + * subnet. + */ + DEBUG(4, "IrLAN: Sending gratuitous ARP\n"); + in_dev = dev->ip_ptr; + arp_send(ARPOP_REQUEST, ETH_P_ARP, + in_dev->ifa_list->ifa_address, + &dev, + in_dev->ifa_list->ifa_address, + NULL, dev->dev_addr, NULL); } /* diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c --- v2.2.6/linux/net/irda/irlan/irlan_provider.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlan/irlan_provider.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Tue Apr 6 19:08:20 1999 + * Modified at: Thu Apr 22 14:28:52 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, @@ -129,7 +129,7 @@ ASSERT(tsap == self->provider.tsap_ctrl,return;); ASSERT(self->provider.state == IRLAN_IDLE, return;); - /* Check if this provider is unused */ + /* Check if this provider is currently unused */ if (self->daddr == DEV_ADDR_ANY) { /* * Rehash instance, now we have a client (daddr) to serve. @@ -168,14 +168,6 @@ if ((self->access_type == ACCESS_PEER) && (self->client.state == IRLAN_IDLE)) irlan_client_wakeup(self, self->saddr, self->daddr); - - /* - * This provider is now in use, so start a new provider instance to - * serve other clients. This will also change the LM-IAS entry so that - * other clients don't try to connect to us, now that we are busy. - */ - new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE); - self->client.start_new_provider = FALSE; } /* @@ -231,20 +223,20 @@ { int ret; - ret = irlan_provider_extract_params(self, CMD_OPEN_DATA_CHANNEL, skb); + ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb); return ret; } /* - * Function extract_params (skb) + * Function parse_command (skb) * * Extract all parameters from received buffer, then feed them to * check_params for parsing * */ -int irlan_provider_extract_params(struct irlan_cb *self, int cmd, - struct sk_buff *skb) +int irlan_provider_parse_command(struct irlan_cb *self, int cmd, + struct sk_buff *skb) { __u8 *frame; __u8 *ptr; @@ -285,7 +277,7 @@ /* For all parameters */ for (i=0; imagic == IRLAN_MAGIC, return;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRLAN_MAGIC, return -1;); /* Check if already open */ if (self->provider.tsap_ctrl) - return; + return -1; /* * First register well known control TSAP @@ -421,11 +413,13 @@ tsap = irttp_open_tsap(LSAP_ANY, 1, ¬ify); if (!tsap) { DEBUG(2, __FUNCTION__ "(), Got no tsap!\n"); - return; + return -1; } self->provider.tsap_ctrl = tsap; /* Register with LM-IAS */ - irlan_ias_register(self,tsap->stsap_sel); + irlan_ias_register(self, tsap->stsap_sel); + + return 0; } diff -u --recursive --new-file v2.2.6/linux/net/irda/irlan/irlan_provider_event.c linux/net/irda/irlan/irlan_provider_event.c --- v2.2.6/linux/net/irda/irlan/irlan_provider_event.c Wed Mar 10 15:29:52 1999 +++ linux/net/irda/irlan/irlan_provider_event.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Wed Feb 3 21:43:06 1999 + * Modified at: Thu Apr 22 10:46:28 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -108,8 +108,15 @@ switch(event) { case IRLAN_GET_INFO_CMD: /* Be sure to use 802.3 in case of peer mode */ - if (self->access_type == ACCESS_PEER) + if (self->access_type == ACCESS_PEER) { self->media = MEDIA_802_3; + + /* Check if client has started yet */ + if (self->client.state == IRLAN_IDLE) { + /* This should get the client going */ + irlmp_discovery_request(8); + } + } irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, RSP_SUCCESS); @@ -165,7 +172,7 @@ switch(event) { case IRLAN_FILTER_CONFIG_CMD: - irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb); + irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb); irlan_provider_send_reply(self, CMD_FILTER_OPERATION, RSP_SUCCESS); /* Keep state */ @@ -207,7 +214,7 @@ switch(event) { case IRLAN_FILTER_CONFIG_CMD: - irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb); + irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb); irlan_provider_send_reply(self, CMD_FILTER_OPERATION, RSP_SUCCESS); break; diff -u --recursive --new-file v2.2.6/linux/net/irda/irlap.c linux/net/irda/irlap.c --- v2.2.6/linux/net/irda/irlap.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlap.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Stable. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Tue Apr 6 21:07:08 1999 + * Modified at: Fri Apr 23 10:12:29 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -44,9 +44,9 @@ #include hashbin_t *irlap = NULL; -int sysctl_slot_timeout = SLOT_TIMEOUT; +int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ; -static void __irlap_close( struct irlap_cb *self); +static void __irlap_close(struct irlap_cb *self); static char *lap_reasons[] = { "ERROR, NOT USED", @@ -301,27 +301,21 @@ * IrLMP for further processing * */ -inline void irlap_data_indication( struct irlap_cb *self, struct sk_buff *skb) +inline void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb) { - DEBUG( 4, __FUNCTION__ "()\n"); - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); - /* Hide LAP header from IrLMP layer */ - skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); + skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); #ifdef CONFIG_IRDA_COMPRESSION - if ( self->qos_tx.compression.value) { - skb = irlap_decompress_frame( self, skb); - if ( !skb) { - DEBUG( 1, __FUNCTION__ "(), Decompress error!\n"); + if (self->qos_tx.compression.value) { + skb = irlap_decompress_frame(self, skb); + if (!skb) { + DEBUG(1, __FUNCTION__ "(), Decompress error!\n"); return; } } #endif - irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb); + irlmp_link_data_indication(self->notify.instance, LAP_RELIABLE, skb); } /* @@ -515,22 +509,22 @@ info.discovery = discovery; /* Check if the slot timeout is within limits */ - if ( sysctl_slot_timeout < 2) { - DEBUG( 1, __FUNCTION__ - "(), to low value for slot timeout!\n"); - sysctl_slot_timeout = 2; + if (sysctl_slot_timeout < 20) { + ERROR(__FUNCTION__ + "(), to low value for slot timeout!\n"); + sysctl_slot_timeout = 20; } /* * Highest value is actually 8, but we allow higher since * some devices seems to require it. */ - if ( sysctl_slot_timeout > 16) { - DEBUG( 1, __FUNCTION__ - "(), to high value for slot timeout!\n"); - sysctl_slot_timeout = 16; + if (sysctl_slot_timeout > 160) { + ERROR(__FUNCTION__ + "(), to high value for slot timeout!\n"); + sysctl_slot_timeout = 160; } - self->slot_timeout = sysctl_slot_timeout; + self->slot_timeout = sysctl_slot_timeout * HZ / 1000; irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info); } else { @@ -807,24 +801,18 @@ { int usecs; int speed; - int bytes = 0; + int bytes ; - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); - ASSERT( qos != NULL, return;); - /* Get QoS values. */ speed = qos->baud_rate.value; usecs = qos->min_turn_time.value; /* No need to calculate XBOFs for speeds over 115200 bps */ - if ( speed > 115200) { + if (speed > 115200) { self->mtt_required = usecs; return; } - DEBUG( 4, __FUNCTION__ "(), delay=%d usecs\n", usecs); - /* * Send additional BOF's for the next frame for the requested * min turn time, so now we must calculate how many chars (XBOF's) we @@ -832,8 +820,6 @@ */ bytes = speed * usecs / 10000000; - DEBUG( 4, __FUNCTION__ "(), xbofs delay = %d\n", bytes); - self->xbofs_delay = bytes; } @@ -1028,7 +1014,7 @@ self->qos_tx.data_size.value = 64; self->qos_tx.additional_bofs.value = 11; - irlap_flush_all_queues( self); + irlap_flush_all_queues(self); self->disconnect_pending = FALSE; } @@ -1079,11 +1065,10 @@ /* * Initialize timeout values, some of the rules are listed on - * page 92 in IrLAP. Divide by 10 since the kernel timers has a - * resolution of 10 ms. + * page 92 in IrLAP. */ - self->poll_timeout = qos->max_turn_time.value / 10; - self->final_timeout = qos->max_turn_time.value / 10; + self->poll_timeout = qos->max_turn_time.value * HZ / 1000; + self->final_timeout = qos->max_turn_time.value * HZ / 1000; self->wd_timeout = self->poll_timeout * 2; #ifdef CONFIG_IRDA_COMPRESSION diff -u --recursive --new-file v2.2.6/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c --- v2.2.6/linux/net/irda/irlap_event.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlap_event.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Aug 16 00:59:29 1997 - * Modified at: Fri Mar 26 14:24:09 1999 + * Modified at: Fri Apr 23 11:55:12 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -40,36 +40,40 @@ #include -static int irlap_state_ndm ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_query ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_reply ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_conn ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_setup ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_xmit_p ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_pclose ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_nrm_p ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); +#if CONFIG_IRDA_FAST_RR +int sysctl_fast_poll_increase = 50; +#endif + +static int irlap_state_ndm (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_query (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_reply (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_conn (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_setup (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_xmit_p (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_pclose (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_nrm_p (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_reset ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_nrm_s ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_xmit_s ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_sclose ( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info); -static int irlap_state_reset_check( struct irlap_cb *, IRLAP_EVENT event, - struct sk_buff *, struct irlap_info *); +static int irlap_state_reset (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_nrm_s (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_xmit_s (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_sclose (struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_reset_check(struct irlap_cb *, IRLAP_EVENT event, + struct sk_buff *, struct irlap_info *); static const char *irlap_event[] = { "DISCOVERY_REQUEST", @@ -145,37 +149,37 @@ /* * Function irda_poll_timer_expired (data) * - * - * + * Poll timer has expired. Normally we must now send a RR frame to the + * remote device */ -static void irlap_poll_timer_expired( unsigned long data) +static void irlap_poll_timer_expired(unsigned long data) { struct irlap_cb *self = (struct irlap_cb *) data; - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LAP_MAGIC, return;); - irlap_do_event( self, POLL_TIMER_EXPIRED, NULL, NULL); + irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL); } -void irlap_start_poll_timer( struct irlap_cb *self, int timeout) +void irlap_start_poll_timer(struct irlap_cb *self, int timeout) { - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LAP_MAGIC, return;); #ifdef CONFIG_IRDA_FAST_RR - if ( skb_queue_len( &self->tx_list) == 0) { - if ( self->fast_RR == TRUE) { + if (skb_queue_len(&self->tx_list) == 0) { + if (self->fast_RR == TRUE) { /* * Assert that the fast poll timer has not reached the * normal poll timer yet */ - if ( self->fast_RR_timeout < timeout) { + if (self->fast_RR_timeout < timeout) { /* * FIXME: this should be a more configurable * function */ - self->fast_RR_timeout += 15; + self->fast_RR_timeout += (sysctl_fast_poll_increase * HZ/1000); /* Use this fast(er) timeout instead */ timeout = self->fast_RR_timeout; @@ -183,17 +187,20 @@ } else { self->fast_RR = TRUE; - /* Start with just 1 ms */ - self->fast_RR_timeout = 1; - timeout = 1; + /* Start with just 0 ms */ + self->fast_RR_timeout = 0; + timeout = 0; } } else self->fast_RR = FALSE; - DEBUG( 4, __FUNCTION__ "(), Timeout=%d\n", timeout); + DEBUG(4, __FUNCTION__ "(), Timeout=%d\n", timeout); #endif - irda_start_timer( &self->poll_timer, timeout, - (unsigned long) self, irlap_poll_timer_expired); + if (timeout == 0) + irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL); + else + irda_start_timer(&self->poll_timer, timeout, + (unsigned long) self, irlap_poll_timer_expired); } /* @@ -338,25 +345,25 @@ case DISCOVERY_REQUEST: ASSERT( info != NULL, return -1;); - if ( irda_device_is_media_busy( self->irdev)) { + if (irda_device_is_media_busy(self->irdev)) { DEBUG(0, __FUNCTION__ "(), media busy!\n"); /* irlap->log.condition = MEDIA_BUSY; */ /* Always switch state before calling upper layers */ - irlap_next_state( self, LAP_NDM); + irlap_next_state(self, LAP_NDM); /* This will make IrLMP try again */ - irlap_discovery_confirm( self, NULL); + irlap_discovery_confirm(self, NULL); return 0; } self->S = info->S; self->s = info->s; - irlap_send_discovery_xid_frame( self, info->S, info->s, TRUE, - info->discovery); + irlap_send_discovery_xid_frame(self, info->S, info->s, TRUE, + info->discovery); self->s++; - irlap_start_slot_timer( self, self->slot_timeout); + irlap_start_slot_timer(self, self->slot_timeout); irlap_next_state(self, LAP_QUERY); break; @@ -440,38 +447,38 @@ irlap_next_state( self, LAP_QUERY); break; case SLOT_TIMER_EXPIRED: - if ( self->s < self->S) { - irlap_send_discovery_xid_frame( self, self->S, - self->s, TRUE, - self->discovery_cmd); + if (self->s < self->S) { + irlap_send_discovery_xid_frame(self, self->S, + self->s, TRUE, + self->discovery_cmd); self->s++; - irlap_start_slot_timer( self, self->slot_timeout); + irlap_start_slot_timer(self, self->slot_timeout); /* Keep state */ - irlap_next_state( self, LAP_QUERY); + irlap_next_state(self, LAP_QUERY); } else { /* This is the final slot! */ - irlap_send_discovery_xid_frame( self, self->S, 0xff, - TRUE, - self->discovery_cmd); + irlap_send_discovery_xid_frame(self, self->S, 0xff, + TRUE, + self->discovery_cmd); /* Always switch state before calling upper layers */ - irlap_next_state( self, LAP_NDM); + irlap_next_state(self, LAP_NDM); /* * We are now finished with the discovery procedure, * so now we must return the results */ - irlap_discovery_confirm( self, self->discovery_log); + irlap_discovery_confirm(self, self->discovery_log); } break; default: DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event, irlap_event[event]); - if ( skb != NULL) { + if (skb) dev_kfree_skb( skb); - } + ret = -1; break; } @@ -485,37 +492,37 @@ * are waiting for the right time slot to send a response XID frame * */ -static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info) +static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) { discovery_t *discovery_rsp; int ret=0; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == LAP_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == LAP_MAGIC, return -1;); - switch( event) { + switch(event) { case QUERY_TIMER_EXPIRED: DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n", jiffies); - irlap_next_state( self, LAP_NDM); + irlap_next_state(self, LAP_NDM); break; case RECV_DISCOVERY_XID_CMD: - ASSERT( info != NULL, return -1;); + ASSERT(info != NULL, return -1;); /* * Last frame? */ - if ( info->s == 0xff) { - del_timer( &self->query_timer); + if (info->s == 0xff) { + del_timer(&self->query_timer); /* info->log.condition = REMOTE; */ /* Always switch state before calling upper layers */ - irlap_next_state( self, LAP_NDM); + irlap_next_state(self, LAP_NDM); - irlap_discovery_indication( self, info->discovery); + irlap_discovery_indication(self, info->discovery); } else if ((info->s >= self->slot) && (!self->frame_sent)) { discovery_rsp = irlmp_get_discovery_response(); discovery_rsp->daddr = info->daddr; @@ -549,17 +556,17 @@ * layer to accept or refuse connection * */ -static int irlap_state_conn( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info) +static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) { int ret = 0; - DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); + DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == LAP_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == LAP_MAGIC, return -1;); - switch( event) { + switch (event) { case CONNECT_RESPONSE: skb_pull( skb, 11); @@ -762,7 +769,7 @@ DEBUG( 4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", irlap_event[ event], self->vs, self->vr); - switch( event) { + switch (event) { case SEND_I_CMD: ASSERT( skb != NULL, return -1;); DEBUG( 4, __FUNCTION__ "(), Window=%d\n", self->window); @@ -822,7 +829,7 @@ } else { DEBUG( 4, __FUNCTION__ "(), Unable to send! remote busy?\n"); - skb_queue_head( &self->tx_list, skb); + skb_queue_head(&self->tx_list, skb); /* * The next ret is important, because it tells @@ -831,19 +838,19 @@ ret = -EPROTO; } break; + case POLL_TIMER_EXPIRED: + irlap_send_rr_frame(self, CMD_FRAME); + irlap_start_final_timer(self, self->final_timeout); + irlap_next_state(self, LAP_NRM_P); + break; case DISCONNECT_REQUEST: - del_timer( &self->poll_timer); - irlap_wait_min_turn_around( self, &self->qos_tx); - irlap_send_disc_frame( self); - irlap_flush_all_queues( self); - irlap_start_final_timer( self, self->final_timeout); + del_timer(&self->poll_timer); + irlap_wait_min_turn_around(self, &self->qos_tx); + irlap_send_disc_frame(self); + irlap_flush_all_queues(self); + irlap_start_final_timer(self, self->final_timeout); self->retry_count = 0; - irlap_next_state( self, LAP_PCLOSE); - break; - case POLL_TIMER_EXPIRED: - irlap_send_rr_frame( self, CMD_FRAME); - irlap_start_final_timer( self, self->final_timeout); - irlap_next_state( self, LAP_NRM_P); + irlap_next_state(self, LAP_PCLOSE); break; default: DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", @@ -916,117 +923,18 @@ * transmit any frames and is expecting to receive frames only from the * secondary to which transmission permissions has been given. */ -static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info) +static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) { int ret = 0; int ns_status; int nr_status; - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == LAP_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == LAP_MAGIC, return -1;); - switch( event) { - case RECV_RR_RSP: - DEBUG( 4, __FUNCTION__ "(), RECV_RR_FRAME: " - "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n", - self->retry_count, info->nr, self->va, self->vs, - self->vr); - - ASSERT( info != NULL, return -1;); - - /* - * If you get a RR, the remote isn't busy anymore, - * no matter what the NR - */ - self->remote_busy = FALSE; - - /* - * Nr as expected? - */ - ret = irlap_validate_nr_received( self, info->nr); - if ( ret == NR_EXPECTED) { - /* Stop final timer */ - del_timer( &self->final_timer); - - /* Update Nr received */ - irlap_update_nr_received( self, info->nr); - - /* - * Got expected NR, so reset the retry_count. This - * is not done by the IrLAP standard , which is - * strange! DB. - */ - self->retry_count = 0; - irlap_wait_min_turn_around( self, &self->qos_tx); - - /* Start poll timer */ - irlap_start_poll_timer( self, self->poll_timeout); - - irlap_next_state( self, LAP_XMIT_P); - } else if ( ret == NR_UNEXPECTED) { - ASSERT( info != NULL, return -1;); - /* - * Unexpected nr! - */ - - /* Update Nr received */ - irlap_update_nr_received( self, info->nr); - - DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, " - "vs=%d, vr=%d\n", - self->retry_count, info->nr, self->va, - self->vs, self->vr); - - /* Resend rejected frames */ - irlap_resend_rejected_frames( self, CMD_FRAME); - - /* - * Start only if not running, DB - * TODO: Should this one be here? - */ - /* if ( !self->final_timer.prev) */ -/* irda_start_timer( FINAL_TIMER, self->final_timeout); */ - - /* Keep state */ - irlap_next_state( self, LAP_NRM_P); - } else if ( ret == NR_INVALID) { - DEBUG(1, "irlap_state_nrm_p: received RR with " - "invalid nr !\n"); - del_timer( &self->final_timer); - - irlap_next_state( self, LAP_RESET_WAIT); - - irlap_disconnect_indication( self, - LAP_RESET_INDICATION); - self->xmitflag = TRUE; - } - if (skb) - dev_kfree_skb( skb); - break; - case RECV_RNR_FRAME: - DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, " - "nr=%d, va=%d, vs=%d, vr=%d\n", - self->retry_count, info->nr, self->va, self->vs, - self->vr); - - ASSERT( info != NULL, return -1;); - - /* Stop final timer */ - del_timer( &self->final_timer); - self->remote_busy = TRUE; - - /* Update Nr received */ - irlap_update_nr_received( self, info->nr); - - /* Start poll timer */ - irlap_start_poll_timer( self, self->poll_timeout); - - irlap_next_state( self, LAP_XMIT_P); - - dev_kfree_skb( skb); - break; - case RECV_I_RSP: + switch (event) { + case RECV_I_RSP: /* Optimize for the common case */ /* FIXME: must check for remote_busy below */ #ifdef CONFIG_IRDA_FAST_RR /* @@ -1039,8 +947,8 @@ ASSERT( info != NULL, return -1;); - ns_status = irlap_validate_ns_received( self, info->ns); - nr_status = irlap_validate_nr_received( self, info->nr); + ns_status = irlap_validate_ns_received(self, info->ns); + nr_status = irlap_validate_nr_received(self, info->nr); /* * Check for expected I(nformation) frame @@ -1049,7 +957,7 @@ /* * poll bit cleared? */ - if ( !info->pf) { + if (!info->pf) { self->vr = (self->vr + 1) % 8; /* Update Nr received */ @@ -1058,16 +966,16 @@ self->ack_required = TRUE; /* Keep state, do not move this line */ - irlap_next_state( self, LAP_NRM_P); + irlap_next_state(self, LAP_NRM_P); - irlap_data_indication( self, skb); + irlap_data_indication(self, skb); } else { - del_timer( &self->final_timer); + del_timer(&self->final_timer); self->vr = (self->vr + 1) % 8; /* Update Nr received */ - irlap_update_nr_received( self, info->nr); + irlap_update_nr_received(self, info->nr); /* * Got expected NR, so reset the @@ -1077,13 +985,17 @@ self->retry_count = 0; self->ack_required = TRUE; - /* This is the last frame */ - irlap_start_poll_timer( self, self->poll_timeout); - irlap_wait_min_turn_around( self, &self->qos_tx); - /* Do not move this line */ - irlap_next_state( self, LAP_XMIT_P); + irlap_wait_min_turn_around(self, &self->qos_tx); + /* + * Important to switch state before calling + * upper layers + */ + irlap_next_state(self, LAP_XMIT_P); - irlap_data_indication( self, skb); + irlap_data_indication(self, skb); + + /* This is the last frame */ + irlap_start_poll_timer(self, self->poll_timeout); } break; @@ -1091,8 +1003,7 @@ /* * Unexpected next to send (Ns) */ - if (( ns_status == NS_UNEXPECTED) && - ( nr_status == NR_EXPECTED)) + if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED)) { if ( !info->pf) { irlap_update_nr_received( self, info->nr); @@ -1125,8 +1036,7 @@ /* * Unexpected next to receive (Nr) */ - if (( ns_status == NS_EXPECTED) && - ( nr_status == NR_UNEXPECTED)) + if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED)) { if ( info->pf) { self->vr = (self->vr + 1) % 8; @@ -1169,8 +1079,8 @@ * Unexpected next to send (Ns) and next to receive (Nr) * Not documented by IrLAP! */ - if (( ns_status == NS_UNEXPECTED) && - ( nr_status == NR_UNEXPECTED)) + if ((ns_status == NS_UNEXPECTED) && + (nr_status == NR_UNEXPECTED)) { DEBUG( 4, "IrLAP: unexpected nr and ns!\n"); if ( info->pf) { @@ -1194,37 +1104,137 @@ /* * Invalid NR or NS */ - if (( nr_status == NR_INVALID) || ( ns_status == NS_INVALID)) { - if ( info->pf) { - del_timer( &self->final_timer); + if ((nr_status == NR_INVALID) || (ns_status == NS_INVALID)) { + if (info->pf) { + del_timer(&self->final_timer); - irlap_next_state( self, LAP_RESET_WAIT); + irlap_next_state(self, LAP_RESET_WAIT); - irlap_disconnect_indication( self, LAP_RESET_INDICATION); + irlap_disconnect_indication(self, LAP_RESET_INDICATION); self->xmitflag = TRUE; } else { - del_timer( &self->final_timer); + del_timer(&self->final_timer); - irlap_disconnect_indication( self, LAP_RESET_INDICATION); + irlap_disconnect_indication(self, LAP_RESET_INDICATION); self->xmitflag = FALSE; } break; } DEBUG(1, __FUNCTION__ "(), Not implemented!\n"); - DEBUG(1, __FUNCTION__ "(), event=%s, ns_status=%d, nr_status=%d\n", - irlap_event[ event], ns_status, nr_status); + DEBUG(1, __FUNCTION__ + "(), event=%s, ns_status=%d, nr_status=%d\n", + irlap_event[ event], ns_status, nr_status); break; case RECV_UI_FRAME: /* poll bit cleared? */ - if ( !info->pf) { - irlap_unit_data_indication( self, skb); - irlap_next_state( self, LAP_NRM_P); + if (!info->pf) { + irlap_unit_data_indication(self, skb); + irlap_next_state(self, LAP_NRM_P); } else { + del_timer(&self->final_timer); + irlap_unit_data_indication(self, skb); + irlap_start_poll_timer(self, self->poll_timeout); + } + break; + case RECV_RR_RSP: + DEBUG(4, __FUNCTION__ "(), RECV_RR_FRAME: " + "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, self->vs, + self->vr); + + ASSERT(info != NULL, return -1;); + + /* + * If you get a RR, the remote isn't busy anymore, + * no matter what the NR + */ + self->remote_busy = FALSE; + + /* + * Nr as expected? + */ + ret = irlap_validate_nr_received(self, info->nr); + if (ret == NR_EXPECTED) { + /* Stop final timer */ + del_timer(&self->final_timer); + + /* Update Nr received */ + irlap_update_nr_received(self, info->nr); + + /* + * Got expected NR, so reset the retry_count. This + * is not done by the IrLAP standard , which is + * strange! DB. + */ + self->retry_count = 0; + irlap_wait_min_turn_around(self, &self->qos_tx); + + irlap_next_state(self, LAP_XMIT_P); + + /* Start poll timer */ + irlap_start_poll_timer(self, self->poll_timeout); + } else if (ret == NR_UNEXPECTED) { + ASSERT( info != NULL, return -1;); + /* + * Unexpected nr! + */ + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, " + "vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, + self->vs, self->vr); + + /* Resend rejected frames */ + irlap_resend_rejected_frames( self, CMD_FRAME); + + /* + * Start only if not running, DB + * TODO: Should this one be here? + */ + /* if ( !self->final_timer.prev) */ +/* irda_start_timer( FINAL_TIMER, self->final_timeout); */ + + /* Keep state */ + irlap_next_state( self, LAP_NRM_P); + } else if (ret == NR_INVALID) { + DEBUG(1, "irlap_state_nrm_p: received RR with " + "invalid nr !\n"); del_timer( &self->final_timer); - irlap_unit_data_indication( self, skb); - irlap_start_poll_timer( self, self->poll_timeout); + + irlap_next_state( self, LAP_RESET_WAIT); + + irlap_disconnect_indication( self, + LAP_RESET_INDICATION); + self->xmitflag = TRUE; } + if (skb) + dev_kfree_skb( skb); + break; + case RECV_RNR_FRAME: + DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, " + "nr=%d, va=%d, vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, self->vs, + self->vr); + + ASSERT( info != NULL, return -1;); + + /* Stop final timer */ + del_timer( &self->final_timer); + self->remote_busy = TRUE; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + irlap_next_state( self, LAP_XMIT_P); + + /* Start poll timer */ + irlap_start_poll_timer( self, self->poll_timeout); + + dev_kfree_skb( skb); break; case RECV_FRMR_RSP: del_timer( &self->final_timer); @@ -1322,8 +1332,8 @@ * awaiting reset of disconnect request. * */ -int irlap_state_reset_wait( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info) +static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) { int ret = 0; @@ -1368,19 +1378,19 @@ * reply. * */ -int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, - struct sk_buff *skb, struct irlap_info *info) +static int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) { int ret = 0; - DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]); + DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]); - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == LAP_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == LAP_MAGIC, return -1;); - switch( event) { + switch(event) { case RECV_DISC_FRAME: - del_timer( &self->final_timer); + del_timer(&self->final_timer); irlap_apply_default_connection_parameters( self); @@ -1398,8 +1408,10 @@ irlap_reset_confirm(); self->remote_busy = FALSE; - irlap_start_poll_timer( self, self->poll_timeout); + irlap_next_state( self, LAP_XMIT_P); + + irlap_start_poll_timer( self, self->poll_timeout); break; case FINAL_TIMER_EXPIRED: if ( self->retry_count < 3) { @@ -1540,53 +1552,8 @@ ASSERT( self != NULL, return -1;); ASSERT( self->magic == LAP_MAGIC, return -1;); - switch( event) { - case RECV_RR_CMD: - self->retry_count = 0; - - /* - * Nr as expected? - */ - nr_status = irlap_validate_nr_received( self, info->nr); - if ( nr_status == NR_EXPECTED) { - if (( skb_queue_len( &self->tx_list) > 0) && - ( self->window > 0)) { - self->remote_busy = FALSE; - - /* Update Nr received */ - irlap_update_nr_received( self, info->nr); - del_timer( &self->wd_timer); - - irlap_wait_min_turn_around( self, &self->qos_tx); - irlap_next_state( self, LAP_XMIT_S); - } else { - self->remote_busy = FALSE; - /* Update Nr received */ - irlap_update_nr_received( self, info->nr); - irlap_wait_min_turn_around( self, &self->qos_tx); - - irlap_send_rr_frame( self, RSP_FRAME); - - irlap_start_wd_timer( self, self->wd_timeout); - irlap_next_state( self, LAP_NRM_S); - } - } else if ( nr_status == NR_UNEXPECTED) { - self->remote_busy = FALSE; - irlap_update_nr_received( self, info->nr); - irlap_resend_rejected_frames( self, RSP_FRAME); - - irlap_start_wd_timer( self, self->wd_timeout); - - /* Keep state */ - irlap_next_state( self, LAP_NRM_S); - } else { - DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n"); - } - if ( skb) - dev_kfree_skb( skb); - - break; - case RECV_I_CMD: + switch(event) { + case RECV_I_CMD: /* Optimize for the common case */ /* FIXME: must check for remote_busy below */ DEBUG( 4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, " "vr=%d, pf=%d\n", irlap_event[event], info->nr, @@ -1765,6 +1732,51 @@ } } break; + case RECV_RR_CMD: + self->retry_count = 0; + + /* + * Nr as expected? + */ + nr_status = irlap_validate_nr_received( self, info->nr); + if ( nr_status == NR_EXPECTED) { + if (( skb_queue_len( &self->tx_list) > 0) && + ( self->window > 0)) { + self->remote_busy = FALSE; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + del_timer( &self->wd_timer); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_next_state( self, LAP_XMIT_S); + } else { + self->remote_busy = FALSE; + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + irlap_wait_min_turn_around( self, &self->qos_tx); + + irlap_send_rr_frame( self, RSP_FRAME); + + irlap_start_wd_timer( self, self->wd_timeout); + irlap_next_state( self, LAP_NRM_S); + } + } else if ( nr_status == NR_UNEXPECTED) { + self->remote_busy = FALSE; + irlap_update_nr_received( self, info->nr); + irlap_resend_rejected_frames( self, RSP_FRAME); + + irlap_start_wd_timer( self, self->wd_timeout); + + /* Keep state */ + irlap_next_state( self, LAP_NRM_S); + } else { + DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n"); + } + if ( skb) + dev_kfree_skb( skb); + + break; case RECV_SNRM_CMD: del_timer( &self->wd_timer); DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n"); @@ -1897,7 +1909,3 @@ return ret; } - - - - diff -u --recursive --new-file v2.2.6/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c --- v2.2.6/linux/net/irda/irlap_frame.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlap_frame.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 10:27:26 1997 - * Modified at: Tue Apr 6 16:35:21 1999 + * Modified at: Fri Apr 23 09:30:42 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Resrved. @@ -48,13 +48,10 @@ * need to do this since it's per packet relevant information. * */ -void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb) +static inline void irlap_insert_mtt(struct irlap_cb *self, struct sk_buff *skb) { struct irlap_skb_cb *cb; - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); - cb = (struct irlap_skb_cb *) skb->cb; cb->magic = LAP_MAGIC; @@ -71,8 +68,6 @@ /* Reset XBOF's delay (used only for getting min turn time) */ self->xbofs_delay = 0; - - DEBUG( 4, __FUNCTION__ "(), using %d xbofs\n", cb->xbofs); } /* @@ -83,10 +78,11 @@ */ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb) { - /* Some init stuff */ + /* Some common init stuff */ skb->dev = self->netdev; skb->h.raw = skb->nh.raw = skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); + skb->priority = TC_PRIO_BESTEFFORT; /* * Insert MTT (min. turn time) into skb, so that the device driver @@ -534,13 +530,10 @@ * Build and transmit RR (Receive Ready) frame. Notice that it is currently * only possible to send RR frames with the poll bit set. */ -void irlap_send_rr_frame( struct irlap_cb *self, int command) +void irlap_send_rr_frame(struct irlap_cb *self, int command) { - struct sk_buff *skb = NULL; + struct sk_buff *skb; __u8 *frame; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); skb = dev_alloc_skb(32); if (!skb) @@ -553,8 +546,6 @@ frame[1] = RR | PF_BIT | (self->vr << 5); - DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); - irlap_queue_xmit(self, skb); } @@ -569,27 +560,7 @@ struct sk_buff *skb, struct irlap_info *info, int command) { - __u8 *frame; - - frame = skb->data; - info->nr = frame[1] >> 5; - - DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies); - - /* - * Make sure the state-machine is in the right state for receiving, - * if not, then we just discard the received frame for now! - * TODO: check if we should queue this frame, or make tty tell that - * it is receiving frames until the frame is delivered instead of - * until it is outside a frame. - */ -#if 0 - if ((self->state != LAP_NRM_P) && (self->state != LAP_NRM_S)) { - DEBUG(0, __FUNCTION__ "(), Wrong state, dropping frame!\n"); - dev_kfree_skb(skb); - return; - } -#endif + info->nr = skb->data[1] >> 5; /* Check if this is a command or a response frame */ if (command) @@ -676,16 +647,7 @@ { struct sk_buff *tx_skb; - DEBUG( 4, __FUNCTION__ "()\n"); - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); - - /* Initialize variables */ - tx_skb = NULL; - - if ( skb->data[1] == I_FRAME) { + if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before @@ -693,10 +655,10 @@ */ skb->data[1] = I_FRAME | (self->vs << 1); - /* * Copy buffer */ - tx_skb = skb_clone( skb, GFP_ATOMIC); - if ( tx_skb == NULL) { - dev_kfree_skb( skb); + /* Copy buffer */ + tx_skb = skb_clone(skb, GFP_ATOMIC); + if (tx_skb == NULL) { + dev_kfree_skb(skb); return; } @@ -704,12 +666,12 @@ * make sure the skb->sk accounting of memory usage is sane */ if (skb->sk != NULL) - skb_set_owner_w( tx_skb, skb->sk); + skb_set_owner_w(tx_skb, skb->sk); /* * Insert frame in store, in case of retransmissions */ - skb_queue_tail( &self->wx_list, skb); + skb_queue_tail(&self->wx_list, skb); self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; @@ -718,7 +680,7 @@ irlap_send_i_frame( self, tx_skb, CMD_FRAME); } else { DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n"); - irlap_send_ui_frame( self, skb, CMD_FRAME); + irlap_send_ui_frame(self, skb, CMD_FRAME); self->window -= 1; } } @@ -731,17 +693,8 @@ { struct sk_buff *tx_skb; - DEBUG( 4, __FUNCTION__ "()\n"); - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); - - /* Initialize variables */ - tx_skb = NULL; - /* Is this reliable or unreliable data? */ - if ( skb->data[1] == I_FRAME) { + if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before @@ -750,9 +703,9 @@ skb->data[1] = I_FRAME | (self->vs << 1); /* Copy buffer */ - tx_skb = skb_clone( skb, GFP_ATOMIC); - if ( tx_skb == NULL) { - dev_kfree_skb( skb); + tx_skb = skb_clone(skb, GFP_ATOMIC); + if (tx_skb == NULL) { + dev_kfree_skb(skb); return; } @@ -760,20 +713,20 @@ * make sure the skb->sk accounting of memory usage is sane */ if (skb->sk != NULL) - skb_set_owner_w( tx_skb, skb->sk); + skb_set_owner_w(tx_skb, skb->sk); /* * Insert frame in store, in case of retransmissions */ - skb_queue_tail( &self->wx_list, skb); + skb_queue_tail(&self->wx_list, skb); /* * Set poll bit if necessary. We do this to the copied * skb, since retransmitted need to set or clear the poll - * bit depending on when * they are sent. + * bit depending on when they are sent. */ /* Stop P timer */ - del_timer( &self->poll_timer); + del_timer(&self->poll_timer); tx_skb->data[1] |= PF_BIT; @@ -781,24 +734,24 @@ self->ack_required = FALSE; self->window = self->window_size; - irlap_start_final_timer( self, self->final_timeout); + irlap_start_final_timer(self, self->final_timeout); - irlap_send_i_frame( self, tx_skb, CMD_FRAME); + irlap_send_i_frame(self, tx_skb, CMD_FRAME); } else { - DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n"); + DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n"); - del_timer( &self->poll_timer); + del_timer(&self->poll_timer); - if ( self->ack_required) { - irlap_send_ui_frame( self, skb, CMD_FRAME); - irlap_send_rr_frame( self, CMD_FRAME); + if (self->ack_required) { + irlap_send_ui_frame(self, skb, CMD_FRAME); + irlap_send_rr_frame(self, CMD_FRAME); self->ack_required = FALSE; } else { skb->data[1] |= PF_BIT; - irlap_send_ui_frame( self, skb, CMD_FRAME); + irlap_send_ui_frame(self, skb, CMD_FRAME); } self->window = self->window_size; - irlap_start_final_timer( self, self->final_timeout); + irlap_start_final_timer(self, self->final_timeout); } } @@ -926,7 +879,7 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == LAP_MAGIC, return;); - DEBUG( 4, __FUNCTION__ "(), retry_count=%d\n", self->retry_count); + DEBUG(2, __FUNCTION__ "(), retry_count=%d\n", self->retry_count); /* Initialize variables */ skb = tx_skb = NULL; @@ -939,7 +892,11 @@ while ( skb != NULL) { irlap_wait_min_turn_around( self, &self->qos_tx); - tx_skb = skb_clone( skb, GFP_ATOMIC); + /* We copy the skb to be retransmitted since we will have to + * modify it. Cloning will confuse packet sniffers + */ + /* tx_skb = skb_clone( skb, GFP_ATOMIC); */ + tx_skb = skb_copy(skb, GFP_ATOMIC); if ( tx_skb == NULL) { /* Unlink tx_skb from list */ tx_skb->next = tx_skb->prev = NULL; @@ -997,12 +954,12 @@ * If send window > 1 then send frame with pf * bit cleared */ - if (( self->window > 1) && - skb_queue_len( &self->tx_list) > 0) + if ((self->window > 1) && + skb_queue_len(&self->tx_list) > 0) { - irlap_send_data_primary( self, skb); + irlap_send_data_primary(self, skb); } else { - irlap_send_data_primary_poll( self, skb); + irlap_send_data_primary_poll(self, skb); } } } @@ -1057,6 +1014,15 @@ /* Insert next to receive (Vr) */ frame[1] |= (self->vr << 5); /* insert nr */ +#if 0 + { + int ns; + ns = (frame[1] >> 1) & 0x07; /* Next to send */ + + DEBUG(0, __FUNCTION__ "(), ns=%d\n", ns); + } +#endif + irlap_queue_xmit(self, skb); } @@ -1070,30 +1036,13 @@ struct sk_buff *skb, struct irlap_info *info, int command) { - __u8 *frame; - - frame = skb->data; - - info->nr = frame[1] >> 5; /* Next to receive */ - info->pf = frame[1] & PF_BIT; /* Final bit */ - info->ns = (frame[1] >> 1) & 0x07; /* Next to send */ + info->nr = skb->data[1] >> 5; /* Next to receive */ + info->pf = skb->data[1] & PF_BIT; /* Final bit */ + info->ns = (skb->data[1] >> 1) & 0x07; /* Next to send */ DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", info->ns, info->nr, info->pf>>4, jiffies); - /* - * Make sure the state-machine is in the right state for receiving, - * if not, then we just discard the received frame for now! - * TODO: check if we should queue this frame, or make tty tell that - * it is receiving frames until the frame is delivered instead of - * until it is outside a frame. - */ - if ((self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) { - DEBUG(0, __FUNCTION__ "(), Wrong state, dropping frame!\n"); - dev_kfree_skb(skb); - return; - } - /* Check if this is a command or a response frame */ if (command) irlap_do_event(self, RECV_I_CMD, skb, info); @@ -1266,7 +1215,7 @@ ASSERT( self != NULL, return -1;); ASSERT( self->magic == LAP_MAGIC, return -1;); - ASSERT(( skb != NULL) && (skb->len > 1), return -1;); + ASSERT( skb->len > 1, return -1;); frame = skb->data; diff -u --recursive --new-file v2.2.6/linux/net/irda/irlmp.c linux/net/irda/irlmp.c --- v2.2.6/linux/net/irda/irlmp.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlmp.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Stable. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Wed Apr 7 17:31:48 1999 + * Modified at: Fri Apr 23 09:13:24 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -719,9 +719,12 @@ */ void irlmp_discovery_request(int nslots) { - DEBUG(4, __FUNCTION__ "(), nslots=%d\n", nslots); + /* Check if user wants to override the default */ + if (nslots == DISCOVERY_DEFAULT_SLOTS) + nslots = sysctl_discovery_slots; + /* * If discovery is already running, then just return the current * discovery log @@ -877,10 +880,8 @@ * Send some data to peer device * */ -void irlmp_data_request( struct lsap_cb *self, struct sk_buff *skb) +void irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb) { - DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(skb != NULL, return;); ASSERT(self != NULL, return;); ASSERT(self->magic == LMP_LSAP_MAGIC, return;); @@ -898,14 +899,8 @@ * Got data from LAP layer so pass it up to upper layer * */ -void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) +inline void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) { - DEBUG(4, __FUNCTION__ "()\n"); - - ASSERT(self != NULL, return;); - ASSERT(self->magic == LMP_LSAP_MAGIC, return;); - ASSERT(skb != NULL, return;); - /* Hide LMP header from layer above */ skb_pull(skb, LMP_HEADER); diff -u --recursive --new-file v2.2.6/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c --- v2.2.6/linux/net/irda/irlmp_event.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlmp_event.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Thu Apr 8 16:26:41 1999 + * Modified at: Fri Apr 23 08:57:23 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -114,16 +114,16 @@ }; /* Do connection control events */ -void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, - struct sk_buff *skb) +void irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) { - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); - DEBUG( 4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n", - irlmp_event[ event], irlmp_state[ self->lsap_state]); + DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n", + irlmp_event[ event], irlmp_state[ self->lsap_state]); - (*lsap_state[ self->lsap_state]) ( self, event, skb); + (*lsap_state[self->lsap_state]) (self, event, skb); } /* @@ -132,23 +132,21 @@ * Do IrLAP control events * */ -void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, - struct sk_buff *skb) +void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) { - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); - DEBUG( 4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n", - irlmp_event[event], - irlmp_state[self->lap_state]); + DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n", + irlmp_event[event], + irlmp_state[self->lap_state]); - (*lap_state[ self->lap_state]) ( self, event, skb); + (*lap_state[self->lap_state]) (self, event, skb); } void irlmp_discovery_timer_expired( unsigned long data) { -/* struct irlmp_cb *self = ( struct irlmp_cb *) data; */ - DEBUG(4, "IrLMP, discovery timer expired!\n"); if (sysctl_discovery) @@ -306,8 +304,8 @@ * ACTIVE, IrLAP connection is active * */ -static void irlmp_state_active( struct lap_cb *self, IRLMP_EVENT event, - struct sk_buff *skb) +static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) { struct lsap_cb *lsap; struct lsap_cb *lsap_current; @@ -343,7 +341,7 @@ /* Keep state */ break; case LM_LAP_DISCONNECT_REQUEST: - DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n"); + DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n"); /* * Need to find out if we should close IrLAP or not. If there @@ -357,7 +355,7 @@ break; case LM_LAP_IDLE_TIMEOUT: if (hashbin_get_size(self->lsaps) == 0) { - DEBUG(0, __FUNCTION__ + DEBUG(2, __FUNCTION__ "(), no more LSAPs so time to close IrLAP\n"); irlmp_next_lap_state(self, LAP_STANDBY); @@ -365,7 +363,7 @@ } break; case LM_LAP_DISCONNECT_INDICATION: - DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n"); + DEBUG(4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n"); irlmp_next_lap_state( self, LAP_STANDBY); @@ -525,18 +523,36 @@ * DATA_TRANSFER_READY * */ -static void irlmp_state_dtr( struct lsap_cb *self, IRLMP_EVENT event, - struct sk_buff *skb) +static void irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) { LM_REASON reason; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); - ASSERT( self->lap != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(self->lap != NULL, return;); - switch( event) { + switch (event) { + case LM_DATA_REQUEST: /* Optimize for the common case */ + irlmp_send_data_pdu(self->lap, self->dlsap_sel, + self->slsap_sel, FALSE, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; + case LM_DATA_INDICATION: /* Optimize for the common case */ + irlmp_data_indication(self, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; + case LM_UDATA_REQUEST: + ASSERT(skb != NULL, return;); + irlmp_send_data_pdu(self->lap, self->dlsap_sel, + self->slsap_sel, TRUE, skb); + break; + case LM_UDATA_INDICATION: + irlmp_udata_indication(self, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; case LM_CONNECT_REQUEST: DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, " "error, LSAP already connected\n"); @@ -548,65 +564,45 @@ /* Keep state */ break; case LM_DISCONNECT_REQUEST: - ASSERT( skb != NULL, return;); + ASSERT(skb != NULL, return;); - irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, - self->slsap_sel, DISCONNECT, skb); - irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, + self->slsap_sel, DISCONNECT, skb); + irlmp_next_lsap_state(self, LSAP_DISCONNECTED); /* Try to close the LAP connection if its still there */ - if ( self->lap) { - DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n"); - irlmp_do_lap_event( self->lap, - LM_LAP_DISCONNECT_REQUEST, - NULL); + if (self->lap) { + DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n"); + irlmp_do_lap_event(self->lap, + LM_LAP_DISCONNECT_REQUEST, + NULL); } - - break; - case LM_DATA_REQUEST: - ASSERT( skb != NULL, return;); - irlmp_send_data_pdu( self->lap, self->dlsap_sel, - self->slsap_sel, FALSE, skb); - /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ - break; - case LM_UDATA_REQUEST: - ASSERT( skb != NULL, return;); - irlmp_send_data_pdu( self->lap, self->dlsap_sel, - self->slsap_sel, TRUE, skb); - break; - case LM_DATA_INDICATION: - irlmp_data_indication( self, skb); - /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ - break; - case LM_UDATA_INDICATION: - irlmp_udata_indication( self, skb); - /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ break; case LM_LAP_DISCONNECT_INDICATION: - irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + irlmp_next_lsap_state(self, LSAP_DISCONNECTED); - reason = irlmp_convert_lap_reason( self->lap->reason); + reason = irlmp_convert_lap_reason(self->lap->reason); - irlmp_disconnect_indication( self, reason, NULL); + irlmp_disconnect_indication(self, reason, NULL); break; case LM_DISCONNECT_INDICATION: - irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + irlmp_next_lsap_state(self, LSAP_DISCONNECTED); - ASSERT( self->lap != NULL, return;); - ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;); + ASSERT(self->lap != NULL, return;); + ASSERT(self->lap->magic == LMP_LAP_MAGIC, return;); ASSERT(skb != NULL, return;); ASSERT(skb->len > 3, return;); reason = skb->data[3]; /* Try to close the LAP connection */ - DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n"); + DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n"); irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); - irlmp_disconnect_indication( self, reason, skb); + irlmp_disconnect_indication(self, reason, skb); break; default: - DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event); + DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event); break; } } diff -u --recursive --new-file v2.2.6/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c --- v2.2.6/linux/net/irda/irlmp_frame.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlmp_frame.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 02:09:59 1997 - * Modified at: Tue Apr 6 18:31:11 1999 + * Modified at: Fri Apr 23 09:12:23 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli @@ -34,30 +34,24 @@ #include #include -static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap, - __u8 slsap, int status, hashbin_t *); +static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap, + __u8 slsap, int status, hashbin_t *); -inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, - int expedited, struct sk_buff *skb) +inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, + int expedited, struct sk_buff *skb) { __u8 *frame; - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); - frame = skb->data; frame[0] = dlsap; frame[1] = slsap; - if ( expedited) { + if (expedited) { DEBUG( 4, __FUNCTION__ "(), sending expedited data\n"); irlap_data_request( self->irlap, skb, FALSE); - } else { - DEBUG( 4, __FUNCTION__ "(), sending reliable data\n"); - irlap_data_request( self->irlap, skb, TRUE); - } + } else + irlap_data_request( self->irlap, skb, TRUE); } /* @@ -98,18 +92,17 @@ * Used by IrLAP to pass received data frames to IrLMP layer * */ -void irlmp_link_data_indication( struct lap_cb *self, int reliable, - struct sk_buff *skb) +void irlmp_link_data_indication(struct lap_cb *self, int reliable, + struct sk_buff *skb) { - __u8 *fp; - __u8 slsap_sel; /* Source (this) LSAP address */ - __u8 dlsap_sel; /* Destination LSAP address */ struct lsap_cb *lsap; + __u8 slsap_sel; /* Source (this) LSAP address */ + __u8 dlsap_sel; /* Destination LSAP address */ + __u8 *fp; - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); - ASSERT( skb->len > 2, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); + ASSERT(skb->len > 2, return;); fp = skb->data; @@ -124,7 +117,7 @@ * Check if this is an incoming connection, since we must deal with * it in a different way than other established connections. */ - if ((fp[0] & CONTROL_BIT) && ( fp[2] == CONNECT_CMD)) { + if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) { DEBUG(3,"Incoming connection, source LSAP=%d, dest LSAP=%d\n", slsap_sel, dlsap_sel); @@ -184,10 +177,17 @@ break; } } else if (reliable == LAP_RELIABLE) { - /* Must be pure data */ - irlmp_do_lsap_event( lsap, LM_DATA_INDICATION, skb); + /* Optimize and bypass the state machine if possible */ + if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY) + irlmp_data_indication(lsap, skb); + else + irlmp_do_lsap_event(lsap, LM_DATA_INDICATION, skb); } else if (reliable == LAP_UNRELIABLE) { - irlmp_do_lsap_event( lsap, LM_UDATA_INDICATION, skb); + /* Optimize and bypass the state machine if possible */ + if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY) + irlmp_data_indication(lsap, skb); + else + irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb); } } @@ -297,8 +297,6 @@ irlmp_add_discovery_log(irlmp->cachelog, log); irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL); - - DEBUG( 4, __FUNCTION__ "() -->\n"); } #ifdef CONFIG_IRDA_CACHE_LAST_LSAP @@ -324,36 +322,31 @@ { struct lsap_cb *lsap; - ASSERT( self != NULL, return NULL;); - ASSERT( self->magic == LMP_LAP_MAGIC, return NULL;); - /* * Optimize for the common case. We assume that the last frame * received is in the same connection as the last one, so check in * cache first to avoid the linear search */ #ifdef CONFIG_IRDA_CACHE_LAST_LSAP - if (( irlmp->cache.valid) && - ( irlmp->cache.slsap_sel == slsap_sel) && - ( irlmp->cache.dlsap_sel == dlsap_sel)) + if ((irlmp->cache.valid) && + (irlmp->cache.slsap_sel == slsap_sel) && + (irlmp->cache.dlsap_sel == dlsap_sel)) { return (irlmp->cache.lsap); } #endif - lsap = ( struct lsap_cb *) hashbin_get_first(queue); - while ( lsap != NULL) { + lsap = (struct lsap_cb *) hashbin_get_first(queue); + while (lsap != NULL) { /* * If this is an incomming connection, then the destination * LSAP selector may have been specified as LM_ANY so that * any client can connect. In that case we only need to check * if the source LSAP (in our view!) match! */ - if (( status == CONNECT_CMD) && - ( lsap->slsap_sel == slsap_sel) && - ( lsap->dlsap_sel == LSAP_ANY)) + if ((status == CONNECT_CMD) && + (lsap->slsap_sel == slsap_sel) && + (lsap->dlsap_sel == LSAP_ANY)) { - DEBUG( 4,"Incoming connection: Setting dlsap_sel=%d\n", - dlsap_sel); lsap->dlsap_sel = dlsap_sel; #ifdef CONFIG_IRDA_CACHE_LAST_LSAP @@ -364,15 +357,15 @@ /* * Check if source LSAP and dest LSAP selectors match. */ - if (( lsap->slsap_sel == slsap_sel) && - ( lsap->dlsap_sel == dlsap_sel)) + if ((lsap->slsap_sel == slsap_sel) && + (lsap->dlsap_sel == dlsap_sel)) { #ifdef CONFIG_IRDA_CACHE_LAST_LSAP - irlmp_update_cache( lsap); + irlmp_update_cache(lsap); #endif return lsap; } - lsap = ( struct lsap_cb *) hashbin_get_next( queue); + lsap = ( struct lsap_cb *) hashbin_get_next(queue); } /* Sorry not found! */ diff -u --recursive --new-file v2.2.6/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c --- v2.2.6/linux/net/irda/irlpt/irlpt_cli.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlpt/irlpt_cli.c Sat Apr 24 17:50:06 1999 @@ -518,8 +518,8 @@ * Fixed to match changes in iriap.h, DB. * */ -void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value, - void *priv) +void irlpt_client_get_value_confirm(int result, __u16 obj_id, + struct ias_value *value, void *priv) { struct irlpt_info info; struct irlpt_cb *self; @@ -534,7 +534,7 @@ ASSERT( self->magic == IRLPT_MAGIC, return;); /* Check if request succeeded */ - if ( !value) { + if (result != IAS_SUCCESS) { DEBUG( 0, __FUNCTION__ "(), got NULL value!\n"); irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, &info); diff -u --recursive --new-file v2.2.6/linux/net/irda/irmod.c linux/net/irda/irmod.c --- v2.2.6/linux/net/irda/irmod.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irmod.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Dec 15 13:55:39 1997 - * Modified at: Mon Mar 29 09:06:52 1999 + * Modified at: Mon Apr 12 11:31:01 1999 * Modified by: Dag Brattli * * Copyright (c) 1997 Dag Brattli, All Rights Reserved. @@ -50,12 +50,12 @@ struct irda_cb irda; /* One global instance */ #ifdef CONFIG_IRDA_DEBUG -__u32 irda_debug = IRDA_DEBUG; +__u32 irda_debug = IRDA_DEBUG_LEVEL; #endif extern void irda_proc_register(void); extern void irda_proc_unregister(void); -extern int irda_sysctl_register(void); +extern int irda_sysctl_register(void); extern void irda_sysctl_unregister(void); extern void irda_proto_init(struct net_proto *pro); @@ -265,22 +265,6 @@ irlmp_cleanup(); } #endif /* MODULE */ - -/* - * Function irda_lock (lock) - * - * Lock variable. Returns false if the lock is already set. - * - */ -inline int irda_lock(int *lock) -{ - if (test_and_set_bit( 0, (void *) lock)) { - DEBUG(3, __FUNCTION__ - "(), Trying to lock, already locked variable!\n"); - return FALSE; - } - return TRUE; -} /* * Function irda_unlock (lock) diff -u --recursive --new-file v2.2.6/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c --- v2.2.6/linux/net/irda/irsysctl.c Wed Mar 10 15:29:53 1999 +++ linux/net/irda/irsysctl.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun May 24 22:12:06 1998 - * Modified at: Mon Jan 25 13:55:54 1999 + * Modified at: Fri Apr 23 09:46:38 1999 * Modified by: Dag Brattli * * Copyright (c) 1997 Dag Brattli, All Rights Reserved. @@ -36,6 +36,7 @@ extern int sysctl_discovery; extern int sysctl_discovery_slots; extern int sysctl_slot_timeout; +extern int sysctl_fast_poll_increase; int sysctl_compression = 0; extern char sysctl_devname[]; @@ -52,7 +53,11 @@ { COMPRESSION, "compression", &sysctl_compression, sizeof(int), 0644, NULL, &proc_dointvec }, #ifdef CONFIG_IRDA_DEBUG - { DEBUG, "debug", &irda_debug, + { DEBUG, "debug", &irda_debug, + sizeof(int), 0644, NULL, &proc_dointvec }, +#endif +#ifdef CONFIG_IRDA_FAST_RR + { SLOTS, "fast_poll_increase", &sysctl_fast_poll_increase, sizeof(int), 0644, NULL, &proc_dointvec }, #endif { SLOTS, "discovery_slots", &sysctl_discovery_slots, diff -u --recursive --new-file v2.2.6/linux/net/irda/irttp.c linux/net/irda/irttp.c --- v2.2.6/linux/net/irda/irttp.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irttp.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Thu Mar 25 10:27:08 1999 + * Modified at: Sat Apr 10 10:32:21 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -639,7 +640,6 @@ struct sk_buff *userdata) { struct sk_buff *skb; - __u16 tmp_be; __u8 *frame; __u8 n; @@ -703,8 +703,8 @@ frame[2] = 0x01; /* MaxSduSize */ frame[3] = 0x02; /* Value length */ - tmp_be = cpu_to_be16((__u16) max_sdu_size); - memcpy(frame+4, &tmp_be, 2); + put_unaligned(cpu_to_be16((__u16) max_sdu_size), + (__u16 *)(frame+4)); } else { /* Insert plain TTP header */ frame = skb_push(skb, TTP_HEADER); @@ -728,11 +728,10 @@ __u32 max_seg_size, struct sk_buff *skb) { struct tsap_cb *self; - __u16 tmp_cpu; - __u8 *frame; - __u8 n; int parameters; + __u8 *frame; __u8 plen, pi, pl; + __u8 n; DEBUG(4, __FUNCTION__ "()\n"); @@ -770,14 +769,26 @@ pi = frame[2]; pl = frame[3]; - ASSERT(pl == 2, return;); - - memcpy(&tmp_cpu, frame+4, 2); /* Align value */ - be16_to_cpus(&tmp_cpu); /* Convert to host order */ - self->tx_max_sdu_size = tmp_cpu; + switch (pl) { + case 1: + self->tx_max_sdu_size = *(frame+4); + break; + case 2: + self->tx_max_sdu_size = + be16_to_cpu(get_unaligned((__u16 *)(frame+4))); + break; + case 4: + self->tx_max_sdu_size = + be32_to_cpu(get_unaligned((__u32 *)(frame+4))); + break; + default: + printk(KERN_ERR __FUNCTION__ + "() illegal value length for max_sdu_size!\n"); + self->tx_max_sdu_size = 0; + }; DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", - self->tx_max_sdu_size); + self->tx_max_sdu_size); } DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", @@ -804,11 +815,10 @@ { struct tsap_cb *self; struct lsap_cb *lsap; - __u16 tmp_cpu; - __u8 *frame; int parameters; - int n; + __u8 *frame; __u8 plen, pi, pl; + __u8 n; self = (struct tsap_cb *) instance; @@ -818,9 +828,6 @@ lsap = (struct lsap_cb *) sap; - /* FIXME: just remove this when we know its working */ - ASSERT(max_seg_size == qos->data_size.value, return;); - self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel); @@ -836,18 +843,31 @@ parameters = frame[0] & 0x80; if (parameters) { - DEBUG(4, __FUNCTION__ "(), Contains parameters!\n"); + DEBUG(3, __FUNCTION__ "(), Contains parameters!\n"); plen = frame[1]; pi = frame[2]; pl = frame[3]; - ASSERT(pl == 2, return;); + switch (pl) { + case 1: + self->tx_max_sdu_size = *(frame+4); + break; + case 2: + self->tx_max_sdu_size = + be16_to_cpu(get_unaligned((__u16 *)(frame+4))); + break; + case 4: + self->tx_max_sdu_size = + be32_to_cpu(get_unaligned((__u32 *)(frame+4))); + break; + default: + printk(KERN_ERR __FUNCTION__ + "() illegal value length for max_sdu_size!\n"); + self->tx_max_sdu_size = 0; + }; - memcpy(&tmp_cpu, frame+4, 2); /* Align value */ - be16_to_cpus(&tmp_cpu); /* Convert to host order */ - self->tx_max_sdu_size = tmp_cpu; - DEBUG(4, __FUNCTION__ "(), MaxSduSize=%d\n", + DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size); } @@ -873,7 +893,6 @@ struct sk_buff *userdata) { struct sk_buff *skb; - __u32 tmp_be; __u8 *frame; __u8 n; @@ -932,8 +951,8 @@ frame[2] = 0x01; /* MaxSduSize */ frame[3] = 0x02; /* Value length */ - tmp_be = cpu_to_be16((__u16)max_sdu_size); - memcpy(frame+4, &tmp_be, 2); + put_unaligned(cpu_to_be16((__u16) max_sdu_size), + (__u16 *)(frame+4)); } else { /* Insert TTP header */ frame = skb_push(skb, TTP_HEADER); diff -u --recursive --new-file v2.2.6/linux/net/irda/qos.c linux/net/irda/qos.c --- v2.2.6/linux/net/irda/qos.c Wed Mar 10 15:29:53 1999 +++ linux/net/irda/qos.c Sat Apr 24 17:50:06 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Sep 9 00:00:26 1997 - * Modified at: Mon Feb 1 09:56:21 1999 + * Modified at: Mon Apr 12 11:49:24 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -70,7 +70,7 @@ qos->compression.bits &= new->compression.bits; #endif - irda_qos_bits_to_value( qos); + irda_qos_bits_to_value(qos); } /* diff -u --recursive --new-file v2.2.6/linux/net/irda/wrapper.c linux/net/irda/wrapper.c --- v2.2.6/linux/net/irda/wrapper.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/wrapper.c Sat Apr 24 17:50:06 1999 @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: wrapper.c - * Version: 1.0 + * Version: 1.1 * Description: SIR wrapper layer * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Mar 26 21:52:53 1999 + * Modified at: Wed Apr 21 12:45:55 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , @@ -34,9 +34,7 @@ #include #include -#define MIN_LENGTH 14 - -inline static int stuff_byte( __u8 byte, __u8 *buf); +inline static int stuff_byte(__u8 byte, __u8 *buf); /* * Function async_wrap (skb, *tx_buff) @@ -44,17 +42,17 @@ * Makes a new buffer with wrapping and stuffing, should check that * we don't get tx buffer overflow. */ -int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize) +int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize) { - __u8 byte; - int i, n; + int i; + int n; int xbofs; union { __u16 value; __u8 bytes[2]; } fcs; - ASSERT( skb != NULL, return 0;); + ASSERT(skb != NULL, return 0;); /* Initialize variables */ fcs.value = INIT_FCS; @@ -72,33 +70,31 @@ */ if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) { DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n"); - xbofs = 11; + xbofs = 10; } else xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs; - for (i=0; ilen; i++) { - byte = skb->data[i]; - /* * Check for the possibility of tx buffer overflow. We use * bufsize-5 since the maximum number of bytes that can be * transmitted after this point is 5. */ - if ( n > buffsize-5) { - printk( KERN_WARNING - "IrDA Wrapper: TX-buffer overflow!\n"); - return n; - } - n+=stuff_byte( byte, tx_buff+n); - fcs.value = IR_FCS( fcs.value, byte); + ASSERT(n < (buffsize-5), return n;); + + n += stuff_byte(skb->data[i], tx_buff+n); + fcs.value = IR_FCS(fcs.value, skb->data[i]); } /* Insert CRC in little endian format (LSB first) */ @@ -111,7 +107,16 @@ n += stuff_byte(fcs.bytes[0], tx_buff+n); #endif tx_buff[n++] = EOF; - + +#if 0 + { + int i; + + for (i=0;istats.rx_dropped++; @@ -132,18 +137,14 @@ } /* Align IP header to 20 bytes */ - skb_reserve( skb, 1); + skb_reserve(skb, 1); - ASSERT( len-2 > 0, return;); - /* Copy data without CRC */ - skb_put( skb, len-2); - memcpy( skb->data, buf, len-2); + memcpy(skb_put(skb, len-2), buf, len-2); /* * Feed it to IrLAP layer */ - /* memcpy(skb_put(skb,count), ax->rbuff, count); */ skb->dev = &idev->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); @@ -159,18 +160,18 @@ * Parse and de-stuff frame received from the IR-port * */ -void async_unwrap_char( struct irda_device *idev, __u8 byte) +void async_unwrap_char(struct irda_device *idev, __u8 byte) { /* State machine for receiving frames */ - switch( idev->rx_buff.state) { + switch (idev->rx_buff.state) { case OUTSIDE_FRAME: - switch( byte) { + switch(byte) { case BOF: idev->rx_buff.state = BEGIN_FRAME; idev->rx_buff.in_frame = TRUE; break; case XBOF: - idev->xbofs++; + /* idev->xbofs++; */ break; case EOF: irda_device_set_media_busy( idev, TRUE); @@ -180,9 +181,8 @@ } break; case BEGIN_FRAME: - switch ( byte) { + switch (byte) { case BOF: - /* Continue */ break; case CE: @@ -198,28 +198,29 @@ break; default: /* Got first byte of frame */ - idev->rx_buff.data[ idev->rx_buff.len++] = byte; + idev->rx_buff.data = idev->rx_buff.head; + idev->rx_buff.len = 0; + + idev->rx_buff.data[idev->rx_buff.len++] = byte; - idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte); + idev->rx_buff.fcs = IR_FCS(INIT_FCS, byte); idev->rx_buff.state = INSIDE_FRAME; break; } break; case LINK_ESCAPE: - switch ( byte) { + switch (byte) { case BOF: /* New frame? */ idev->rx_buff.state = BEGIN_FRAME; - idev->rx_buff.len = 0; - irda_device_set_media_busy( idev, TRUE); + irda_device_set_media_busy(idev, TRUE); break; case CE: - DEBUG( 4, "WARNING: State not defined\n"); + DEBUG(4, "WARNING: State not defined\n"); break; case EOF: /* Abort frame */ idev->rx_buff.state = OUTSIDE_FRAME; - idev->rx_buff.len = 0; break; default: /* @@ -227,28 +228,25 @@ * following CE, IrLAP p.114 */ byte ^= IR_TRANS; - if ( idev->rx_buff.len < idev->rx_buff.truesize) { - idev->rx_buff.data[ idev->rx_buff.len++] = byte; - + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs, byte); idev->rx_buff.state = INSIDE_FRAME; } else { - DEBUG( 1, __FUNCTION__ + DEBUG(1, __FUNCTION__ "(), Rx buffer overflow, aborting\n"); idev->rx_buff.state = OUTSIDE_FRAME; - idev->rx_buff.len = 0; } break; } break; case INSIDE_FRAME: - switch ( byte) { + switch (byte) { case BOF: /* New frame? */ idev->rx_buff.state = BEGIN_FRAME; - idev->rx_buff.len = 0; - irda_device_set_media_busy( idev, TRUE); + irda_device_set_media_busy(idev, TRUE); break; case CE: /* Stuffed char */ @@ -262,14 +260,12 @@ /* * Test FCS and deliver frame if it's good */ - if ( idev->rx_buff.fcs == GOOD_FCS) { - async_bump( idev, idev->rx_buff.data, - idev->rx_buff.len); - idev->rx_buff.len = 0; + if (idev->rx_buff.fcs == GOOD_FCS) { + async_bump(idev, idev->rx_buff.data, + idev->rx_buff.len); } else { /* Wrong CRC, discard frame! */ - irda_device_set_media_busy( idev, TRUE); - idev->rx_buff.len = 0; + irda_device_set_media_busy(idev, TRUE); idev->stats.rx_errors++; idev->stats.rx_crc_errors++; @@ -277,16 +273,14 @@ break; default: /* Next byte of frame */ - if ( idev->rx_buff.len < idev->rx_buff.truesize) { - idev->rx_buff.data[ idev->rx_buff.len++] = byte; - - idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, - byte); + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; + idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs, + byte); } else { - DEBUG( 1, __FUNCTION__ - "(), Rx buffer overflow, aborting\n"); + DEBUG(1, __FUNCTION__ + "(), Rx buffer overflow, aborting\n"); idev->rx_buff.state = OUTSIDE_FRAME; - idev->rx_buff.len = 0; } break; } @@ -301,9 +295,9 @@ * buf. The buffer must at all times be able to have two bytes inserted. * */ -inline static int stuff_byte( __u8 byte, __u8 *buf) +inline static int stuff_byte(__u8 byte, __u8 *buf) { - switch ( byte) { + switch (byte) { case BOF: /* FALLTHROUGH */ case EOF: /* FALLTHROUGH */ case CE: diff -u --recursive --new-file v2.2.6/linux/net/netsyms.c linux/net/netsyms.c --- v2.2.6/linux/net/netsyms.c Tue Mar 23 14:35:48 1999 +++ linux/net/netsyms.c Sat Apr 24 17:51:48 1999 @@ -21,6 +21,9 @@ #include #include #include +#ifdef CONFIG_HIPPI +#include +#endif #include #ifdef CONFIG_BRIDGE @@ -45,6 +48,8 @@ #include extern struct net_proto_family inet_family_ops; +extern __u32 sysctl_wmem_max; +extern __u32 sysctl_rmem_max; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include @@ -474,6 +479,15 @@ EXPORT_SYMBOL(kill_fasync); EXPORT_SYMBOL(if_port_text); + +#ifdef CONFIG_HIPPI +EXPORT_SYMBOL(hippi_type_trans); +EXPORT_SYMBOL(init_hippi_dev); +EXPORT_SYMBOL(unregister_hipdev); +#endif + +EXPORT_SYMBOL(sysctl_wmem_max); +EXPORT_SYMBOL(sysctl_rmem_max); #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) #include diff -u --recursive --new-file v2.2.6/linux/net/sched/cls_fw.c linux/net/sched/cls_fw.c --- v2.2.6/linux/net/sched/cls_fw.c Mon Mar 29 11:09:12 1999 +++ linux/net/sched/cls_fw.c Thu Apr 22 19:45:20 1999 @@ -7,6 +7,10 @@ * 2 of the License, or (at your option) any later version. * * Authors: Alexey Kuznetsov, + * + * Changes: + * Karlis Peisenieks : 990415 : fw_walk off by one + * Karlis Peisenieks : 990415 : fw_delete killed all the filter (and kernel). */ #include @@ -146,7 +150,7 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg) { - struct fw_head *head = (struct fw_head*)xchg(&tp->root, NULL); + struct fw_head *head = (struct fw_head*)tp->root; struct fw_filter *f = (struct fw_filter*)arg; struct fw_filter **fp; @@ -273,7 +277,7 @@ if (arg->stop) return; - for (h = 0; h <= 256; h++) { + for (h = 0; h < 256; h++) { struct fw_filter *f; for (f = head->ht[h]; f; f = f->next) { diff -u --recursive --new-file v2.2.6/linux/net/sched/cls_rsvp.h linux/net/sched/cls_rsvp.h --- v2.2.6/linux/net/sched/cls_rsvp.h Mon Mar 29 11:09:12 1999 +++ linux/net/sched/cls_rsvp.h Thu Apr 22 19:45:20 1999 @@ -193,23 +193,23 @@ && src[2] == f->src[2] #endif ) { + *res = f->res; RSVP_POLICE(); matched: - if (f->tunnelhdr == 0) { - *res = f->res; + if (f->tunnelhdr == 0) return 0; - } else { - tunnelid = f->res.classid; - nhptr = (void*)(xprt + f->tunnelhdr - sizeof(*nhptr)); - goto restart; - } + + tunnelid = f->res.classid; + nhptr = (void*)(xprt + f->tunnelhdr - sizeof(*nhptr)); + goto restart; } } /* And wildcard bucket... */ for (f = s->ht[16]; f; f = f->next) { + *res = f->res; RSVP_POLICE(); goto matched; } diff -u --recursive --new-file v2.2.6/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c --- v2.2.6/linux/net/sched/sch_cbq.c Tue Mar 23 14:35:48 1999 +++ linux/net/sched/sch_cbq.c Sat Apr 24 17:51:48 1999 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.2.6/linux/net/sched/sch_sfq.c linux/net/sched/sch_sfq.c --- v2.2.6/linux/net/sched/sch_sfq.c Tue Mar 23 14:35:48 1999 +++ linux/net/sched/sch_sfq.c Sat Apr 24 17:51:48 1999 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.2.6/linux/net/socket.c linux/net/socket.c --- v2.2.6/linux/net/socket.c Tue Mar 23 14:35:48 1999 +++ linux/net/socket.c Thu Apr 22 19:45:20 1999 @@ -279,8 +279,8 @@ inode->i_mode = S_IFSOCK|S_IRWXUGO; inode->i_sock = 1; - inode->i_uid = current->uid; - inode->i_gid = current->gid; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; sock->inode = inode; init_waitqueue(&sock->wait); @@ -1135,7 +1135,7 @@ /* Check whether to allocate the iovec area*/ err = -ENOMEM; iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > 1 /* UIO_FASTIOV */) { + if (msg_sys.msg_iovlen > UIO_FASTIOV) { iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); if (!iov) goto out_put; @@ -1147,6 +1147,11 @@ goto out_freeiov; total_len = err; + err = -ENOBUFS; + + /* msg_controllen must fit to int */ + if (msg_sys.msg_controllen > INT_MAX) + goto out_freeiov; ctl_len = msg_sys.msg_controllen; if (ctl_len) { diff -u --recursive --new-file v2.2.6/linux/scripts/ksymoops/oops.c linux/scripts/ksymoops/oops.c --- v2.2.6/linux/scripts/ksymoops/oops.c Mon Mar 29 11:09:12 1999 +++ linux/scripts/ksymoops/oops.c Thu Apr 22 19:24:52 1999 @@ -288,7 +288,7 @@ errno = 0; eip_relative = strtoul(string[5], NULL, 16); if (errno) { -#if 0 +#ifdef __sparc__ /* Try strtoull also, e.g. sparc binutils print <_PC+0xfffffffffffffd58> */ errno = 0; eip_relative = strtoull(string[5], NULL, 16);